32 位 cdecl 處理結構
填充
請記住,結構的成員通常是填充的,以確保它們在自然邊界上對齊:
struct t
{
int a, b, c, d; // a is at offset 0, b at 4, c at 8, d at 0ch
char e; // e is at 10h
short f; // f is at 12h (naturally aligned)
long g; // g is at 14h
char h; // h is at 18h
long i; // i is at 1ch (naturally aligned)
};
作為引數(通過引用傳遞)
通過引用傳遞時,指向記憶體中結構的指標將作為堆疊上的第一個引數傳遞。這相當於傳遞一個自然大小(32 位)的整數值; 有關詳細資訊,請參閱 32 位 cdecl 。
作為引數(按值傳遞)
當通過值傳遞時,結構完全複製在堆疊上,遵循原始記憶體佈局( 即,第一個成員將位於較低地址)。
int __attribute__((cdecl)) foo(struct t a);
struct t s = {0, -1, 2, -3, -4, 5, -6, 7, -8};
foo(s);
; Assembly call
push DWORD 0fffffff8h ; i (-8)
push DWORD 0badbad07h ; h (7), pushed as DWORD to naturally align i, upper bytes can be garbage
push DWORD 0fffffffah ; g (-6)
push WORD 5 ; f (5)
push WORD 033fch ; e (-4), pushed as WORD to naturally align f, upper byte can be garbage
push DWORD 0fffffffdh ; d (-3)
push DWORD 2 ; c (2)
push DWORD 0ffffffffh ; b (-1)
push DWORD 0 ; a (0)
call foo
add esp, 20h
作為返回值
除非它們是微不足道的 1 ,否則在返回之前將結構體複製到呼叫者提供的緩衝區中。這相當於隱藏了第一個引數 struct S *retval
(其中 struct S
是結構的型別)。
該函式必須返回此指標,指向 eax
中的返回值; 允許呼叫者依賴 eax
將指標指向返回值,該指標在 call
之前推動。
struct S
{
unsigned char a, b, c;
};
struct S foo(); // compiled as struct S* foo(struct S* _out)
出於堆疊清理的目的,隱藏引數不會新增到引數計數中,因為它必須由被呼叫者處理。
sub esp, 04h ; allocate space for the struct
; call to foo
push esp ; pointer to the output buffer
call foo
add esp, 00h ; still as no parameters have been passed
在上面的示例中,結構將儲存在堆疊的頂部。
struct S foo()
{
struct S s;
s.a = 1; s.b = -2; s.c = 3;
return s;
}
; Assembly code
push ebx
mov eax, DWORD PTR [esp+08h] ; access hidden parameter, it is a pointer to a buffer
mov ebx, 03fe01h ; struct value, can be held in a register
mov DWORD [eax], ebx ; copy the structure into the output buffer
pop ebx
ret 04h ; remove the hidden parameter from the stack
; EAX = pointer to the output buffer
1 普通結構只包含一個非結構非陣列型別的成員(最多 32 位)。對於這樣的結構,該成員的值只是在 eax
暫存器中返回。 (在針對 Linux 的 GCC 中觀察到此行為)
Windows 版本的 cdecl 與 System V ABI 的呼叫約定不同:允許普通結構包含最多兩個非結構非陣列型別的成員(最大為 32 位)。這些值在 eax
和 edx
中返回,就像 64 位整數一樣。 (已針對 MSVC 和 Clang 定位 Win32 觀察到此行為。)