2012-06-01 75 views
4

我正在閱讀一些linux程序集手冊,並發現了關於使用printf()函數的想法。我需要它以二進制形式輸出寄存器值到終端,但現在我試圖簡單地用文本測試該函數。Linux X86-64程序集和printf

我被卡住了,因爲segfault時我使用pushq而不是pushl。我怎樣才能改變這個程序輸出字符串和二進制形式的寄存器?

.data 
input_prompt: 
    .string "Hello, world!" 

printf_format: 
    .string "%5d " 

printf_newline: 
    .string "\n" 

size: 
    .long 0 

.text 
.globl main 
main: 
    pushq $input_prompt 
    call printf 

    movl $0, %eax 
    ret 

它是由GCC編譯爲:

gcc tmp.S -o tmp 

回答

10

的Linux(和Windows)x86-64 calling convention有最初的幾個參數在堆棧上不,但在寄存器而不是

http://www.x86-64.org/documentation/abi.pdf(第20頁)

具體來說:

  1. 如果類是MEMORY,請將參數傳遞給堆棧。
  2. 如果類是INTEGER,則使用序列%rdi,%rsi,%rdx,%rcx,%r8和%r9的下一個可用寄存器。
  3. 如果類是SSE,則使用下一個可用的向量寄存器,寄存器按從%xmm0到%xmm7的順序進行。
  4. 如果類是SSEUP,則在最後使用的向量寄存器的下一個可用八字節塊中傳遞八個字節。
  5. 如果該類是X87,X87UP或COMPLEX_X87,它將傳遞到內存中。

INTEGER類是什麼,將適合在一個通用寄存器,所以這是你會使用什麼字符串指針爲好。

+3

[Windows x64調用約定](http://msdn.microsoft.com/zh-cn/library/7kcdt6fy)也會在寄存器中傳遞一些參數,但與Linux調用約定不同(請參閱[「參數傳遞」](http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx)部分)。 –

+0

並且您必須通過'eax = 1'來設置可變參數的數量,並對齊堆棧:http://stackoverflow.com/questions/10324333/does-printf-require-additional-stack-space-on-the- x86-64 || http://stackoverflow.com/questions/14000351/x86-64-linux-assembly-why-printf-with-float-format-string-work-only-with-rsp –