2012-09-05 16 views
1

我知道函數參數是填充目標字的大小,但與什麼?ELF如何填充「短」?

特別是在x86 Linux GNU工具鏈的上下文中,這些函數返回什麼?

int iMysteryMeat(short x) 
{ 
    return *((int *)&x); 
} 
unsigned uMysteryMeat(unsigned short x) 
{ 
    return *((unsigned *)&x); 
} 

的問題是,是否,當手工編碼在組件的功能,有必要通過掩蔽到sterilze「小」參數或「大」的上下文(andlimull)使用它們之前簽署延伸他們。

我也會對這種情況是否有更多的通用或跨平臺標準感興趣。

+1

使用gcc -S然後回來告訴我們! –

+2

你的問題與ELF無關 – TJD

+0

你是對的。這與黑暗中的一槍相同。 – bug

回答

2

這取決於ABI。 ABI需要指定調用者或被調用者(以及如何)擴展小參數的選項。不幸的是,ABI的這部分通常沒有詳細說明,導致不同的編譯器做出不同的選擇。因此,爲了防止用不同的遺留編譯器編譯的代碼之間的不兼容性,大多數現代編譯器(我特別知道的關於i386gcc)在謹慎的方面犯錯,並且兩者兼而有之。

int a(short x) { 
    return x; 
} 
int b(int x); 
int c(short x) { 
    b(x); 
} 

gcc -m32 -O3 -S tmp.c -o tmp.s 

_a: 
pushl %ebp 
movl %esp, %ebp 
movswl 8(%ebp),%eax 
leave 
ret 

_c: 
pushl %ebp 
movl %esp, %ebp 
movswl 8(%ebp),%eax 
movl %eax, 8(%ebp) 
leave 
jmp _b 

注意a不承擔有關其論點的擴展規則,而是延伸它本身。同樣,c確保在將其傳遞給b(通過尾部呼叫)之前擴展其參數。

+0

謝謝你的方法和原因。我實際上是在系統上輔導我的同學,這足以解釋它。 – bug

0
int iMysteryMeat(short x) 
{ 
    return *((int *)&x); 
} 

這是C中未定義的行爲,這違反了別名規則,也可能違反對齊要求。在short不要這樣做。

+0

我很清楚,這是令人反感的C代碼,永遠不會實際使用它,但它有意暴露下面的醜陋。如果你願意的話,我可以在程序集中爲你提供特定的用例。 – bug

+0

作爲未定義的行爲意味着C標準給予了實現的所有自由度來解釋這一點,並沒有給出任何限制。 – ouah

+1

這就是我指定我使用的對象架構和編譯器的原因。可移植性不在窗口中。 – bug

0

雖然基思的回答符合我的問題的精神,但是根據Alex的要求,我想我會爲自己嘗試一下。

有趣的是,在這種情況下,我的例子中更多的文字回答是「垃圾」。

#include <stdio.h> 

int iMysteryMeat(short x) 
{ 
    return *((int *)&x); 
} 
unsigned uMysteryMeat(unsigned short x) 
{ 
    return *((unsigned *)&x); 
} 
int main() 
{ 
    printf("iMeat: 0x%08x\n", iMysteryMeat(-23)); 
    printf("uMeat: 0x%08x\n", uMysteryMeat(-23)); 
    return 0; 
} 

gcc -m32 -S meat.c 

iMysteryMeat: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $4, %esp 
    movl 8(%ebp), %eax 
    movw %ax, -4(%ebp) 
    leal -4(%ebp), %eax 
    movl (%eax), %eax 
    leave 
    ret 
uMysteryMeat: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $4, %esp 
    movl 8(%ebp), %eax 
    movw %ax, -4(%ebp) 
    leal -4(%ebp), %eax 
    movl (%eax), %eax 
    leave 
    ret 

./a.out 
iMeat: 0x0804ffe9 
uMeat: 0x0043ffe9 

正如你所看到的,不僅是overrided通常的符號擴展協議(即Keith的a()比較),它實際上使X爲未初始化的堆棧空間movw,使返回值垃圾的上半部分不管什麼main()都給它。

所以,再次,作爲ouah說,永遠爲此在C和彙編(或一般,真的),總是消毒您輸入