32 位 cdecl 处理整数

作为参数(8,16,32 位)

8,16,32 位整数总是在堆栈上传递为全宽 32 位值 1
不需要扩展,签名或归零。
被调用者将只使用全宽值的下半部分。

//C prototype of the callee
void  __attribute__((cdecl)) foo(char a, short b, int c, long d);

foo(-1, 2, -3, 4);

;Call to foo in assembly

push DWORD 4             ;d, long is 32 bits, nothing special here
push DWORD 0fffffffdh    ;c, int is 32 bits, nothing special here
push DWORD 0badb0002h    ;b, short is 16 bits, higher WORD can be any value
push DWORD 0badbadffh    ;a, char is 8 bits, higher three bytes can be any value
call foo
add esp, 10h             ;Clean up the stack

作为参数(64 位)

使用两次推送在堆栈上传递 64 位值,遵循 littel endian 约定 2 ,首先推高 32 位然后推低位。

//C prototype of the callee
void  __attribute__((cdecl)) foo(char a, short b, int c, long d);

foo(0x0123456789abcdefLL);

;Call to foo in assembly

push DWORD 89abcdefh        ;Higher DWORD of 0123456789abcdef
push DWORD 01234567h        ;Lower DWORD of 0123456789abcdef
call foo
add esp, 08h

作为返回值

AL 中返回 8 位整数,最终破坏整个 eax
AX 中返回 16 位整数,最终破坏整个 eax
EAX 中返回 32 位整数。
EDX:EAX 中返回 64 位整数,其中 EAX 保持低 32 位而 EDX 保持高位。

//C
char foo() { return -1; }

;Assembly
mov al, 0ffh
ret

//C
unsigned short foo() { return 2; }

;Assembly
mov ax, 2
ret

//C
int foo() { return -3; }

;Assembly
mov eax, 0fffffffdh
ret

//C
int foo() { return 4; }

;Assembly
xor edx, edx            ;EDX = 0
mov eax, 4            ;EAX = 4
ret

1 这使堆栈保持 4 字节对齐,即自然字大小。另外,x86 CPU 在长模式下只能推 2 或 4 个字节。

2 在较低地址处降低 DWORD