花样繁多:函数到底能怎么返回值?
eax返回值不假,但是eax 不就4个字节吗,各种代码通过eax返回时到底有多少花样? have a try:
1、 long long
Dump of assembler code for function fun():
=> 0x00401500 <+0>: push %ebp
0x00401501 <+1>: mov %esp,%ebp
0x00401503 <+3>: mov $0x11223344,%eax
0x00401508 <+8>: mov $0x0,%edx
0x0040150d <+13>: pop %ebp
0x0040150e <+14>: ret
End of assembler dump.
Dump of assembler code for function main(int, char**):
0x0040150f <+0>: push %ebp
0x00401510 <+1>: mov %esp,%ebp
0x00401512 <+3>: and $0xfffffff0,%esp
0x00401515 <+6>: sub $0x10,%esp
0x00401518 <+9>: call 0x409650 <__main>
0x0040151d <+14>: call 0x401500 <fun()>
0x00401522 <+19>: mov %eax,0x8(%esp)
0x00401526 <+23>: mov %edx,0xc(%esp)
0x0040152a <+27>: mov $0x0,%eax
0x0040152f <+32>: leave
0x00401530 <+33>: ret
End of assembler dump.
edx小伙加入了。
2、 真 long long。
事实上又拉了一个战友过来
->->post-prompt
Dump of assembler code for function main(int, char**):
0x0040150f <+0>: push %ebp
0x00401510 <+1>: mov %esp,%ebp
0x00401512 <+3>: and $0xfffffff0,%esp
0x00401515 <+6>: sub $0x10,%esp
0x00401518 <+9>: call 0x409650 <__main>
=> 0x0040151d <+14>: call 0x401500 <fun()>
0x00401522 <+19>: mov %eax,0x8(%esp)
0x00401526 <+23>: mov %edx,0xc(%esp) <==注意这里
0x0040152a <+27>: mov $0x0,%eax
0x0040152f <+32>: leave
0x00401530 <+33>: ret
End of assembler dump.
->->pre-prompt
(gdb)
->->prompt
->->post-prompt
Dump of assembler code for function fun():
0x00401500 <+0>: push %ebp
0x00401501 <+1>: mov %esp,%ebp
0x00401503 <+3>: mov $0x11223344,%eax
0x00401508 <+8>: mov $0x0,%edx
0x0040150d <+13>: pop %ebp
0x0040150e <+14>: ret
End of assembler dump.
3、 超long long long long
ecx参战的感觉。
用Intel的吧,大家也方便看一点
fun():
0x00401500 <+0>: push ebp
0x00401501 <+1>: mov ebp,esp
0x00401503 <+3>: sub esp,0xc
=> 0x00401506 <+6>: mov eax,0xab33bc40
0x0040150b <+11>: mov edx,0x89119a22
0x00401510 <+16>: mov ecx,0x403b
0x00401515 <+21>: mov DWORD PTR [ebp-0xc],eax
0x00401518 <+24>: mov DWORD PTR [ebp-0x8],edx
0x0040151b <+27>: mov DWORD PTR [ebp-0x4],ecx
0x0040151e <+30>: fld TBYTE PTR [ebp-0xc]
0x00401521 <+33>: leave
0x00401522 <+34>: ret
4、 真· 超long long long long
long128构造函数:
0x00415fb0 <+0>: push ebp
0x00415fb1 <+1>: mov ebp,esp
0x00415fb3 <+3>: sub esp,0x18
0x00415fb6 <+6>: mov DWORD PTR [ebp-0x4],ecx
0x00415fb9 <+9>: mov eax,DWORD PTR [ebp+0x8]
0x00415fbc <+12>: mov DWORD PTR [ebp-0x10],eax
0x00415fbf <+15>: mov eax,DWORD PTR [ebp+0xc]
0x00415fc2 <+18>: mov DWORD PTR [ebp-0xc],eax
0x00415fc5 <+21>: mov eax,DWORD PTR [ebp+0x10]
0x00415fc8 <+24>: mov DWORD PTR [ebp-0x18],eax
0x00415fcb <+27>: mov eax,DWORD PTR [ebp+0x14]
0x00415fce <+30>: mov DWORD PTR [ebp-0x14],eax
0x00415fd1 <+33>: mov ecx,DWORD PTR [ebp-0x4] <== this
0x00415fd4 <+36>: mov eax,DWORD PTR [ebp-0x10]
0x00415fd7 <+39>: mov edx,DWORD PTR [ebp-0xc]
0x00415fda <+42>: mov DWORD PTR [ecx],eax <== eax, edx合起来就是一个long long
0x00415fdc <+44>: mov DWORD PTR [ecx+0x4],edx
0x00415fdf <+47>: mov ecx,DWORD PTR [ebp-0x4]
0x00415fe2 <+50>: mov eax,DWORD PTR [ebp-0x18]
0x00415fe5 <+53>: mov edx,DWORD PTR [ebp-0x14]
0x00415fe8 <+56>: mov DWORD PTR [ecx+0x8],eax <== 同上,另一个赋值操作
0x00415feb <+59>: mov DWORD PTR [ecx+0xc],edx
=> 0x00415fee <+62>: leave
0x00415fef <+63>: ret 0x10
fun():
0x00401500 <+0>: push ebp
0x00401501 <+1>: mov ebp,esp
0x00401503 <+3>: sub esp,0x10 <==本地的缓冲区
0x00401506 <+6>: mov DWORD PTR [esp+0x8],0x44332211
0x0040150e <+14>: mov DWORD PTR [esp+0xc],0x88776655
0x00401516 <+22>: mov DWORD PTR [esp],0x55667788
0x0040151d <+29>: mov DWORD PTR [esp+0x4],0x11223344 <==把这几个倒霉数字存进去
0x00401525 <+37>: mov ecx,DWORD PTR [ebp+0x8] <==ebp+0x8,这个临时的long128变量地址
0x00401528 <+40>: call 0x415fb0 <long128::long128(long long, long long)>
0x0040152d <+45>: sub esp,0x10 <==栈上的缓冲区释放掉
=> 0x00401530 <+48>: mov eax,DWORD PTR [ebp+0x8] <==变量的地址返回eax……
0x00401533 <+51>: leave
0x00401534 <+52>: ret
main():
0x00401535 <+0>: push ebp
0x00401536 <+1>: mov ebp,esp
0x00401538 <+3>: and esp,0xfffffff0
0x0040153b <+6>: sub esp,0x20
0x0040153e <+9>: call 0x409680 <__main>
0x00401543 <+14>: lea eax,[esp+0x10] <==long128的内存
0x00401547 <+18>: mov DWORD PTR [esp],eax
0x0040154a <+21>: call 0x401500 <fun()> <==别忘了这时候已经赋值给long128 tempA了
=> 0x0040154f <+26>: mov eax,0x0 <== return 0;
0x00401554 <+31>: leave
0x00401555 <+32>: ret
call = push + jmp,
esp => [ EAX ]
aftercall:
esp => [ retnaddr ]
[ EAX ]
1st instruction:
esp => [ ebp ]
[ retnaddr ]
[ EAX ] <= esp+8
上一层预留空间了,学会废物利用了。
5、假·超long long long long
fun():
0x00401500 <+0>: push ebp
0x00401501 <+1>: mov ebp,esp
=> 0x00401503 <+3>: mov eax,DWORD PTR [ebp+0x8] <==long128的地址
0x00401506 <+6>: mov DWORD PTR [eax],0x55667788 <==第一次赋值
0x0040150c <+12>: mov DWORD PTR [eax+0x4],0x11223344
0x00401513 <+19>: mov eax,DWORD PTR [ebp+0x8]
0x00401516 <+22>: mov DWORD PTR [eax+0x8],0x44332211 <==第二次赋值
0x0040151d <+29>: mov DWORD PTR [eax+0xc],0x88776655
0x00401524 <+36>: nop
0x00401525 <+37>: mov eax,DWORD PTR [ebp+0x8]
0x00401528 <+40>: pop ebp
0x00401529 <+41>: ret
main():
0x0040152a <+0>: push ebp
0x0040152b <+1>: mov ebp,esp
0x0040152d <+3>: and esp,0xfffffff0
0x00401530 <+6>: sub esp,0x20
0x00401533 <+9>: call 0x409670 <__main>
0x00401538 <+14>: lea eax,[esp+0x10]
0x0040153c <+18>: mov DWORD PTR [esp],eax
0x0040153f <+21>: call 0x401500 <fun()>
=> 0x00401544 <+26>: mov eax,0x0
0x00401549 <+31>: leave
0x0040154a <+32>: ret
看来跟之前一样。
6、 terminated
多加一句varA.h1++;
0x0040152a <+0>: push ebp
0x0040152b <+1>: mov ebp,esp
0x0040152d <+3>: and esp,0xfffffff0
0x00401530 <+6>: sub esp,0x20
0x00401533 <+9>: call 0x409680 <__main>
=> 0x00401538 <+14>: lea eax,[esp+0x10]
0x0040153c <+18>: mov DWORD PTR [esp],eax
0x0040153f <+21>: call 0x401500 <fun()>
0x00401544 <+26>: mov eax,DWORD PTR [esp+0x10]
0x00401548 <+30>: mov edx,DWORD PTR [esp+0x14]
0x0040154c <+34>: add eax,0x1
0x0040154f <+37>: adc edx,0x0
0x00401552 <+40>: mov DWORD PTR [esp+0x10],eax
0x00401556 <+44>: mov DWORD PTR [esp+0x14],edx
0x0040155a <+48>: mov eax,0x0
0x0040155f <+53>: leave
0x00401560 <+54>: ret
ok done.有空再研究研究其他的。