C code와 nasm 코드의 argument 전달 방식에 대해서..
글쓴이: revival4u / 작성시간: 화, 2007/12/04 - 1:40오전
아까전에 올렸던 내용인데
ndisasm -b 32를 통해 disassemble한 내용을 토대로 다시 작성하였습니다.
C code :
int func(int a, int b, char c, char d, int e, double f, char g){ a = 1+1; b = 2+2; c = 'c'; d = 'd'; e = 1+2; f = 1.0+1.0; g = 'g'; } int main(void){ func(1, 2, 'a', 'b', 3, 1.0, 'c');}
nasm code
00000000 55 push ebp 00000001 89E5 mov ebp,esp 00000003 83EC18 sub esp,byte +0x18 ; 8*4byte의 stack을 사용하겠다... 00000006 8B4510 mov eax,[ebp+0x10] ; 스텍의 세번째(c)를 eax로 00000009 8B5514 mov edx,[ebp+0x14] ; 스텍의 네번째(d)를 edx로 0000000C 8B4D24 mov ecx,[ebp+0x24] ; 스텍의 여덟번째(g)를 ecx로(double이 qword를 차지하므로) 0000000F 8845FC mov [ebp-0x4],al ; char형 변수 c, d를 [ebp-0x4]및 00000012 8855F8 mov [ebp-0x8],dl ; [ebp-0x8]로 복사 00000015 8B451C mov eax,[ebp+0x1c] ; double형 변수 f를 두번에 거쳐 복사 00000018 8945F0 mov [ebp-0x10],eax ; - 0000001B 8B4520 mov eax,[ebp+0x20] ; - 0000001E 8945F4 mov [ebp-0xc],eax ; - 00000021 884DEC mov [ebp-0x14],cl ; char형 변수 g를 복사 00000024 C7450802000000 mov dword [ebp+0x8],0x2 ; a = 1+1; 0000002B C7450C04000000 mov dword [ebp+0xc],0x4 ; b = 2+2; 00000032 C645FC63 mov byte [ebp-0x4],0x63 ; c = 'c'; 00000036 C645F864 mov byte [ebp-0x8],0x64 ; d = 'd'; 0000003A C7451803000000 mov dword [ebp+0x18],0x3 ; e = 1+2; 00000041 DD05A8000000 fld qword [dword 0xa8] ; ?무슨명령어? 00000047 DD5DF0 fstp qword [ebp-0x10] ; ?무슨명령어? 0000004A C645EC67 mov byte [ebp-0x14],0x67 ; g = 'g'; 0000004E C9 leave0000004F C3 ret ...
위와같이 asm과 c가 매칭이 된다.
여기서 질문이..
1. int형 a, b, e는 return address와 push ebp 로 인해 [ebp+0x8]이 첫번째 인자를 가리키므로제가아는것과 같이 인자들을 접근합니다. 하지만 char형과 double형은 왜 ebp 위쪽에 위치한 argument들을 '-'를 통해 아래쪽으로 복사를 하는데 왜 그런 작업을 하는지 이해가 안됩니다.
2. double형은 왜 두번에 나누어 저렇게 복사하게 되는지 또한 구음하구요
3. fld, fstp 명령어들은 무슨역할을 하는지 궁금하네요
읽어주셔서 감사하고
같이 고민해주실분 구합니다~~
Forums:
1번은 잘
1번은 잘 모르겠구요..
2번은 더블형이 64비트이기 때문에 32비트 레지스터에 한번에 못들어가니까 그런것 같습니다.
3번은 f가 앞에 붙어있는건 실수연산용 명령어라고 알고 있습니다. f = 1.0+1.0; 를 연산하는 것일겁니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
상수 계산
아닙니다. 이 경우 식의 모든 부분이 상수이기 때문에 "f = 2.0;"과 같은 결과이고 덧셈은 없습니다.
"연산"이라고 해서 좀
"연산"이라고 해서 좀 애매하긴 했군요.
전 대입(=)을 연산이라고 생각해서 그렇게 답을 했었네요:)
아마 0xa8에 상수 2.0이 저장되어있을 겁니다.
00000041 DD05A8000000 fld qword [dword 0xa8] ; 상수 2.0을 실수레지스터 스택에 로드
00000047 DD5DF0 fstp qword [ebp-0x10] ; 실수레지스터 스택의 st(0)를 스택의 ebp-0x10에 저장
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
음. 아래걸 참고
음. 아래걸 참고 하시는것이
어떠실지.
-----------------------
과거를 알고 싶거든 오늘의 네 모습을 보아라. 그것이 과거의 너니라.
그리고 내일을 알고 싶으냐?
그러면 오늘의 너를 보아라. 그것이 바로 미래의 너니라.
고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"
답변 감사합니다.
죄송한데 마지막분께서 AT&T형식 assembly language로
올려주셨는데...
의도파악이 잘...
어떤점에서 그렇게 올려주셨는지 좀..알려주세요
제가보기엔 비슷해보이는데...
objdump -S
제가 생각하기에, objdump의 -S (--source) 옵션을 쓰면 어셈블리와 C 코드를 알아서 맞춰주니까 ndisasm보다 좋다는 뜻일 듯 합니다.
AT&T 문법이 싫으시면 objdump -M intel -S 로 하시면 인텔 문법으로 나옵니다.
감사합니다
넵 감사합니다~
댓글 달기