2010-01-15 105 views
3

IM只是好奇下面的例子C - 分號的返回值是什麼?

#include<stdio.h> 
int test(); 
int test(){ 
    // int a = 5; 
    // int b = a+1; 
    return ; 
} 
int main(){ 
    printf("%u\n",test()); 
    return 0; 
} 

我與「GCC -Wall -o分號semicolon.c」編譯它來創建可執行 和「GCC -Wall -S semicolon.c」,讓彙編代碼是:

.file "semicolon.c" 
    .text 
.globl test 
    .type test, @function 
test: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $4, %esp 
    leave 
    ret 
    .size test, .-test 
    .section  .rodata 
.LC0: 
    .string "%u\n" 
    .text 
.globl main 
    .type main, @function 
main: 
    leal 4(%esp), %ecx 
    andl $-16, %esp 
    pushl -4(%ecx) 
    pushl %ebp 
    movl %esp, %ebp 
    pushl %ecx 
    subl $20, %esp 
    call test 
    movl %eax, 4(%esp) 
    movl $.LC0, (%esp) 
    call printf 
    movl $0, %eax 
    addl $20, %esp 
    popl %ecx 
    popl %ebp 
    leal -4(%ecx), %esp 
    ret 
    .size main, .-main 
    .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" 
    .section  .note.GNU-stack,"",@progbits 

,因爲我不是這樣的彙編親,我只知道printf的打印什麼是EAX ,但我不完全理解「MOVL%EAX,4(%ESP)」的意思是我假設在調用測試 之前填充eax,但那麼值是多少?什麼意思是4(%esp),esp的意思是什麼?

如果我取消測試()行的printf打印6 - 這是寫在EAX ^^

回答

9

你的彙編語言註釋:

test: 
    pushl %ebp  # Save the frame pointer 
    movl %esp, %ebp # Get the new frame pointer. 
    subl $4, %esp # Allocate some local space on the stack. 
    leave    # Restore the old frame pointer/stack 
    ret 

注意,沒有在測試倒是EAX。

.size test, .-test 
.section  .rodata 
.LC0: 
.string "%u\n" 
.text 
.globl main 
.type main, @function 
main: 
leal 4(%esp), %ecx  # Point past the return address. 
andl $-16, %esp   # Align the stack. 
pushl -4(%ecx)   # Push the return address. 
pushl %ebp    # Save the frame pointer 
movl %esp, %ebp   # Get the new frame pointer. 
pushl %ecx    # save the old top of stack. 
subl $20, %esp   # Allocate some local space (for printf parameters and ?). 
call test    # Call test. 

請注意,在這一點上,沒有什麼修改eax。無論進入主體還是在這裏。

movl %eax, 4(%esp)  # Save eax as a printf argument. 
movl $.LC0, (%esp)  # Send the format string. 
call printf    # Duh. 
movl $0, %eax   # Return zero from main. 
addl $20, %esp   # Deallocate local space. 
popl %ecx    # Restore the old top of stack. 
popl %ebp    # And the old frame pointer. 
leal -4(%ecx), %esp  # Fix the stack pointer, 
ret 

因此,打印出來的是什麼進入主要。正如其他人指出的那樣,它是未定義的:它取決於啓動代碼(或操作系統)以前對eax所做的工作。

+0

很好的解釋。添加一些關於這個主題的更多信息,似乎eax及其在通過堆棧傳遞值時的用法與簡單數據類型(int,double,char,void *,...)類似,但是當它進入更多的結構時編譯器的內存管理髮揮作用。即時通訊還不確定在堆棧上發生什麼情況,以便理解空函數返回結構的空函數,但這是一個更復雜的問題/答案。無論如何 - thx – 2010-01-15 12:17:42

+0

@John:幾乎同樣的事情發生在像'int'和'float'一樣的結構中。它被稱爲_stack垃圾_。無論內存中調用者爲返回值保留的是什麼,返回_returned_。 – 2010-01-15 12:52:58

7

分號沒有返回值,你有什麼是「空回」,喜歡使用的一個從void函數返回 - 所以函數不返回任何東西。

編譯時,這實際上將導致警告:

warning: `return' with no value, in function returning non-void 

而且我沒有看到任何東西放在eax調用test之前。

約4(%esp),這意味着從堆棧指針(esp)+ 4中取值。堆棧中的前一個單詞。

+0

似乎我混合英特爾和AT&T彙編語法,所以你的權利,EAX沒有寫。所以'movl%eax,4(%esp)'意味着eax被推入堆棧,對吧? – 2010-01-15 12:01:27

+0

不,這意味着eax的值存儲在[esp + 4]中,這可能是堆棧 – 2010-01-15 12:14:09

2

int函數的返回值在EAX寄存器中傳遞。測試函數不設置EAX寄存器,因爲沒有返回值。結果因此未定義。

+0

上的一些局部變量,所以結果不是未定義的,但在eax中找到的值是正確的?這在定義上被稱爲'undefined' – 2010-01-15 12:06:29

+0

是的,結果是EAX中的值。由於EAX沒有明確設置,它的值由某個未知的以前的操作決定。這就是我們所說的'未定義'。 – Tomas 2010-01-18 11:12:14

0

分號確實沒有任何價值。

我認爲正確的答案是函數是一個錯誤,或至少有未定義的行爲。這就是爲什麼有-Wall編譯這會產生

semi.c: In function ‘test’: 
semi.c:6: warning: ‘return’ with no value, in function returning non-void 

至於什麼%4,esp擁有......這堆在那裏什麼也沒有上的位置(故意)存儲,所以它可能會返回任何垃圾在該位置被發現。這可能是對函數中的變量進行評估的最後一個表達式(如您的示例中)或完全不同的東西。這就是「未定義」的全部內容。 :)