-
c언어 -> 어셈블리어 변환 연습Rev 2023. 7. 9. 14:39
//test.c #include <stdio.h> int main(int argc, char* argv[]) { ~~~~ .... ~~~~ return 0; }
간단한 c언어 코드이다.
어셈블리어로 바꾸어 본다면 main함수에 대한 프롤로그, 에필로그가 생성된다.
PUSH rbp mov rbp, rsp ~~~~ .... ~~~~ mov eax, 0 pop rbp ret
모든 함수에 대해 프롤로그, 에필로그가 생성이 되고 함수 내 코드에 따라 프롤로그, 에필로그사이에 있는 어셈블리어 코드들도 달라진다.
이렇게 함수의 시작과 끝이 생성이 되면 다음으로는 main 함수 내에 있는 인자 값인 argc, argv에 대한 어셈블리어가 에필로그 다음으로 붙는다.
PUSH rbp mov rbp, rsp DWORD PTR [rbp-4], edi //main함수 인자인 int argc QWORD PTR [rbp-16], rsi //main함수 인자인 char* argv[] ~~~~ .... ~~~~ mov eax, 0 pop rbp ret
이번에는 위 코드에 간단한 덧셈을 추가해보았다.
#include <stdio.h> int main(int argc, char* argv[]){ int a = 1; int b = 2; printf("a+b = %d", a+b); return 0; }
main 함수 내에 변수 a와 b가 선언이 되고 a+b값이 출력이 되는 코드이다.
.LC0: .string "a+b = %d" main: push rbp mov rbp, rsp sub rsp, 32 mov DWORD PTR [rbp-20], edi //main함수 인자인 int argc mov QWORD PTR [rbp-32], rsi //main함수 인자인 char* argv[] mov DWORD PTR [rbp-4], 1 //변수 a의 값 mov DWORD PTR [rbp-8], 2 //변수 b의 값 mov edx, DWORD PTR [rbp-4] // 덧셈을 하기 위해 a의 값을 edx로 이동 mov eax, DWORD PTR [rbp-8] // 덧셈을 하기 위해 b의 값을 eax로 이동 add eax, edx //a+b mov esi, eax //a+b를 한 값을 esi로 이동 mov edi, OFFSET FLAT:.LC0 //printf함수의 첫 인자값 mov eax, 0 //eax 레지스터 초기화 call printf //printf 함수 call mov eax, 0 //eax 레지스터 초기화 leave ret
어셈블리어로 변환이 되면 이렇다.
새로운 코드들이 추가가 되었고, main 함수에 인자 값이었던 argc, argv[]가 저장되는 주솟값이 변화된 것을 볼 수 있다.
rbp-32 //argv[] 8byte rbp-20 //argc 4byte rbp-8 //b의 값:2 rbp-4 //a의 값:1 rbp 스택에는 값이 이렇게 들어가 있을 것이다.
+)
왜 먼저 넣는 argc, argv이 뒤쪽 주소(낮은 값)에 들어가고 a, b 의 값이 앞쪽 주소(높은 값)에 들어가는지 순간 헷갈렸었다.
어셈블리어 코드에서 sub rsp, 32를 해줬으니 일단은 rbp에서 32크기가 생겼을 것이고, 그 사이에 공간에 스택 쌓이는 순서는 매개변수 > 반환 주소값 > 지역변수 이여서 그런것이라 이해를 했다.
++)공간을 먼저 확보하고 넣어야하는 순서에 맞게 넣는 것이라면 스택에 넣는 값의 크기를 늘려 덮어 쓰는것이 가능한가?'Rev' 카테고리의 다른 글
리버싱 핵심 원리 (인라인 패치) (0) 2023.07.29 모르는 어셈블리어 정리 (repne scasb) (0) 2023.07.19 모르는 어셈블리어 정리 (cdq) (0) 2023.07.09