mips 스택프레임
#include <stdio.h>
void a(){
char buf[0x30];
printf("this is a\n");
read(0, buf, 0x30);
b();
}
void b(){
printf("this is b\n");
}
int main(){
printf("this is main\n");
a();
}
위 함수를 예제로 하여 설명해겠다.

프롤로그
addiu sp, sp, -32
sw ra, 28(sp)
sw s8, 24(sp)
move s8, sp
sp에 -32를 빼서 공간을 확보한다.
sw ra, 28(sp) 로 sp + 28 에 ra를 저장한다. 이는 복귀주소를 저장해놓은 것이다. (ret)
sw s8, 24(sp) 로 sp + 24 에 s8을 저장한다. 이는 복귀frame base를 저장해놓은 것이다. (sfp)
move s8, sp 를 통해 s8에 sp 값을 넣는다.
body
이것저것 메인 코드가 실행된다.
에필로그
lw ra, 28(sp)
lw s8, 24(sp)
addiu sp, sp, 32
jr ra
nop
lw ra, 28(sp) 로 이전에 저장해두었던 sp+28 에 값을 ra로 다시 복원한다.
lw s8, 24(sp) 로 이전에 저장해두었던 sp+24 에 값을 s8로 다시 복원한다.
addiu sp, sp, 32 로 sp + 32 를 해서 다시 스택 프레임을 없엔다.
ra (복귀주소) 로 점프한다.
mips 레지스터
zero : 항상 0 이다.
v0-v1 : return 값
a0-a3 : 함수 호출 시 파라미터
t0-t7 : 임시 레지스터
s0-s7 : 함수 호출 시 값이 유지되어야 하는 레지스터 용도, 함수의 데이터 무결성
t8-t9 : 임시 레지스터
gp : 보존되어야 하는 global pointer : 전역변수, 정적 변수에 빠르게 접근하기 위함
sp : stack pointer (= esp x86)
fp/s8 : stack frame pointer or subrountine variable (= ebp x64)
ra : 마지막 subroutine call의 리턴 주소
mips 어셈블리어
자주 쓰이는 어셈블리어를 정리해보았다.
() : register
[] : const int
off : offset (offset 28 이면 28(sp))
위와 같은 형식으로 표현하겠다.
() : 레지스터의 값
[] : 해당 주소에 존재하는 값
off : offset (like 28 about 28(sp))
move (1), (2) : (1) = (2)
addiu (1), (2), const16 : (1) = (2) + const16
sw (1), off16((2)): [(2)+off16] = (1)
lui (1), const16 : (1) = const16 << 16 ( lui reg, 0x42⇒ reg를 0x420000 로 초기화)
ori (1), (2), const16 : (1) = (2) or const16
lw (1), off16((2)) : (1) = [(2)+off]
jalr (1) : jmp (1) and ra = pc+8
jr : jmp ra ( = 함수 복귀)
li (1), IMM32 : (1) = [IMM32]
sltiu (1), (2), const16 : (1) = ((2) < const16)? 1 : 0
beqz (1), off18 : if((1)=0) , PC += off18
bal off18 : ra=PC+8, PC+=off18
jal func : ra = pc+8, PC = func addr
mips는 기본적으로 at&t 문법을 사용한다.
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'mips' 카테고리의 다른 글
mips rop (0) | 2025.03.25 |
---|---|
mips shellcode (0) | 2025.03.18 |
mips - 기본 개념 (0) | 2025.02.16 |
mips 스택프레임
#include <stdio.h>
void a(){
char buf[0x30];
printf("this is a\n");
read(0, buf, 0x30);
b();
}
void b(){
printf("this is b\n");
}
int main(){
printf("this is main\n");
a();
}
위 함수를 예제로 하여 설명해겠다.

프롤로그
addiu sp, sp, -32
sw ra, 28(sp)
sw s8, 24(sp)
move s8, sp
sp에 -32를 빼서 공간을 확보한다.
sw ra, 28(sp) 로 sp + 28 에 ra를 저장한다. 이는 복귀주소를 저장해놓은 것이다. (ret)
sw s8, 24(sp) 로 sp + 24 에 s8을 저장한다. 이는 복귀frame base를 저장해놓은 것이다. (sfp)
move s8, sp 를 통해 s8에 sp 값을 넣는다.
body
이것저것 메인 코드가 실행된다.
에필로그
lw ra, 28(sp)
lw s8, 24(sp)
addiu sp, sp, 32
jr ra
nop
lw ra, 28(sp) 로 이전에 저장해두었던 sp+28 에 값을 ra로 다시 복원한다.
lw s8, 24(sp) 로 이전에 저장해두었던 sp+24 에 값을 s8로 다시 복원한다.
addiu sp, sp, 32 로 sp + 32 를 해서 다시 스택 프레임을 없엔다.
ra (복귀주소) 로 점프한다.
mips 레지스터
zero : 항상 0 이다.
v0-v1 : return 값
a0-a3 : 함수 호출 시 파라미터
t0-t7 : 임시 레지스터
s0-s7 : 함수 호출 시 값이 유지되어야 하는 레지스터 용도, 함수의 데이터 무결성
t8-t9 : 임시 레지스터
gp : 보존되어야 하는 global pointer : 전역변수, 정적 변수에 빠르게 접근하기 위함
sp : stack pointer (= esp x86)
fp/s8 : stack frame pointer or subrountine variable (= ebp x64)
ra : 마지막 subroutine call의 리턴 주소
mips 어셈블리어
자주 쓰이는 어셈블리어를 정리해보았다.
() : register
[] : const int
off : offset (offset 28 이면 28(sp))
위와 같은 형식으로 표현하겠다.
() : 레지스터의 값
[] : 해당 주소에 존재하는 값
off : offset (like 28 about 28(sp))
move (1), (2) : (1) = (2)
addiu (1), (2), const16 : (1) = (2) + const16
sw (1), off16((2)): [(2)+off16] = (1)
lui (1), const16 : (1) = const16 << 16 ( lui reg, 0x42⇒ reg를 0x420000 로 초기화)
ori (1), (2), const16 : (1) = (2) or const16
lw (1), off16((2)) : (1) = [(2)+off]
jalr (1) : jmp (1) and ra = pc+8
jr : jmp ra ( = 함수 복귀)
li (1), IMM32 : (1) = [IMM32]
sltiu (1), (2), const16 : (1) = ((2) < const16)? 1 : 0
beqz (1), off18 : if((1)=0) , PC += off18
bal off18 : ra=PC+8, PC+=off18
jal func : ra = pc+8, PC = func addr
mips는 기본적으로 at&t 문법을 사용한다.
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'mips' 카테고리의 다른 글
mips rop (0) | 2025.03.25 |
---|---|
mips shellcode (0) | 2025.03.18 |
mips - 기본 개념 (0) | 2025.02.16 |