Hello.
I’m trying to understand how fastcall works.
As far as I know, first two integer type arguments are passed in ecx and edx.
I tested several test, but the result was different from what I expected
#1
typedef struct _data_t {
int d;
} data_t;
void attribute((fastcall)) test_suuu(data_t s, unsigned int a, unsigned int b, unsigned int c);
unsigned int a is passed in edx, and the rest are passed in stack (in s, b, c order).
#2 : order of arguments is diff from #1
void attribute((fastcall)) test_usuu(unsigned int a, data_t s, unsigned int b, unsigned int c);
unsigned int a is passed in ecx, and the rest are passed in stack (in s, b, c order)
#3 : attribute((packed)) is diff from #1
typedef struct attribute((packed)) _data_t3 {
int d;
} data_t3;
void attribute((fastcall)) test_s3uu(data_t3 s3, unsigned int a, unsigned int b);
unsigned int a is passed in ecx, and the rest are passed in stack (in s, b, c order)
My questions are as follow
- why struct s in first test is passed in edx not ecx?
- why unsigned b is in second test is passed in stack not edx?
- why ‘packed’ makes a difference?
- where can I find relevant code in llvm?
I’m using i586, linux, llvm 5.02
Build with “clang++ -std=c++11 -ggdb -O0 -gdwarf-4 -fno-omit-frame-pointer -fno-optimize-sibling-calls -o ref_test ref_test.cpp”
(All arguments are used in the function so that they are not optimized out)
Tested with gdb
(gdb) break* test_suuu
(gdb) x/6wx $esp
(gdb) i r