gcc x86 calling conventions

在<<stacktrace如何实现>>的最后介绍stacktrace的时候,是x86 calling convention决定了ebp/esp(base pointer/stack pointer)的使用,通过ebp/esp得到backtrace. 下图是一个概况:

 

gcc x86 calling convention也规定了参数如何传递

1. 32bit规定,函数参数存放在stack上,第一个参数在stack的地址最小,最后一个参数的地址最大。第一个参数紧跟在函数返回地址后面。如上图中的ret eip; arg 1; arg 2.

后来有了个fastcall的attribute,可以把前两个参数放在register(ecx/edx)上传递,其他的通过stack传递。

The relevant attribute is __attribute__((fastcall)). Functions declared with this attribute are called with their first eligible argument in ECX and the second in EDX.

GCC passes arguments on stack in your case because the Linux-x86 ABI specifies that. With the fastcall function attribute you can change that, which of course breaks the ABI and causes all kinds of problems due to that.

A solution could be to swith to x86-64, where the ABI specifies that (some) arguments are passed by registers. Or if you like bleeding edge stuff, the newish x32 ABI is similar to the x86-64 ABI but with 32-bit pointers.

2. x86_64规定,参数可以通过registers传递。可用的registers比较多。

更多的内容可以参考链接的文章<Calling conventionsfor different C++ compilers and operating systems>,里面有一节介绍calling convention。

整个系列的文章<Software optimization resources>

 

参考:

1. https://stackoverflow.com/questions/11575502/make-gcc-pass-the-arguments-by-register

2. https://www.agner.org/optimize/?e=0#0