2017-04-23 264 views
-3

我無法理解如何將此彙編代碼轉換爲C.它非常短,只有幾行,答案應該是一行代碼。如何將彙編代碼轉換爲C?

char_out: 
    subq $8, %esp 
    movsbl %dil, %edi # Parameter 1 in %dil/%edi 
    call putchar  # put char is a C function that writes (prints) 
    addq $8, %rsp  # a single char to stdout (the screen). 
    ret 
void char_out(char P1) 
{ 
    //insert here 
} 
+0

它只是'putchar(P1);' –

+0

詢問某人做你的工作的問題不適用於StackOverflow。向我們展示您迄今爲止所嘗試的內容以及您遇到困難的地方,我們很樂意爲您提供幫助。 –

+0

@olivercharlesworth這是一個很好的笑話,但你爲什麼改變鏈接? –

回答

2
char_out: 
    # Allocate 8 bytes on the stack by subtracting 8 from the stack pointer. 
    # 
    # This is done for conformance to the calling convention expected by the 
    # 'putchar' function, which we're about to call. 
    subq $8, %esp 

    # This is the weirdo AT&T mnemonic for the MOVSX instruction, which does a 
    # move with sign extension. This means that it extends a small value 
    # (here, a BYTE-sized value in DIL) into a larger value (here, a 
    # DWORD-sized value in EDI), in a way that properly accounts for the 
    # value's sign bit. 
    # 
    # This is necessary because the 'putchar' function expects to be passed a 
    # 32-bit 'int' parameter. 
    movsbl %dil, %edi 

    # It's obvious what this does: it calls the 'putchar' function. 
    call putchar 

    # Clean up the stack, undoing what we previously did to the stack pointer 
    # at the top of the function (the 'subq' instruction). 
    addq $8, %rsp 

由於Lashane已經評論說,這彙編代碼相當於下面的C代碼:

void char_out(char P1) 
{ 
    putchar(P1); 
} 

或者,我想你也可以說:

void char_out(char P1) 
{ 
    int temp = (int)P1;  // movsbl 
    putchar(temp); 
} 

但是C編譯器會爲你隱式執行,所以沒有必要明確地顯示擴展轉換。

+0

謝謝,這是非常有幫助的。我唯一的困惑是程序集中subq和addq的用途。你能否詳細說明一下? – ninchicken

+0

不知道還有什麼我可以說,我沒有說過。查看堆棧如何在x86架構上工作。當你想在棧上分配空間時,你從棧指針中減去;當你想釋放這個空間時,你添加到堆棧指針。堆棧指針總是存儲在「ESP」寄存器中,所以這就是'sub'和'add'指令的作用。我也已經解釋了*爲什麼*它正在這樣做,即使你沒有使用堆棧:'putchar'函數顯然期望這是它的調用約定的一部分。這是依賴於實現的,所以我不能說更多。 –

+0

@ninchicken:因爲[64位系統V ABI](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf)需要它。在_3.2.2堆棧幀_它說「_輸入參數區域的末尾應對齊在一個16(32或64,如果 __m256或__m512被傳遞堆棧)字節邊界。換句話說,值 ( %rsp + 8)總是16(32或64)的倍數,當控制轉移到函數入口點 。堆棧指針%rsp始終指向最後分配堆棧的結尾frame_「 –