2017-08-29 314 views
0

我在學習彙編,它在某種程度上是有意義的,但我有一個問題。我有這個源文件hello.sfml如何知道使用哪個整數寄存器

; nasm -felf64 hello.asml && ld hello.o 

    global _start 

    section .text 
_start: 
    ; write(1, message, 13) 
    mov  rax, 1   ; syscall 1 is write 
    mov  rdi, 1   ; file handle 1 is stdout 
    mov  rsi, message ; address of string to output 
    mov  rdx, 13   ; number of bytes in the string 
    syscall     ; invoke OS to write the string 

    ; exit(0) 
    mov  rax, 60   ; syscall 60 is exit 
    xor  rdi, rdi 
    syscall     ; invoke OS to exit 
message: 
    db "Hello, World", 10 ; the 10 is a newline character at the end 

這是完美的。我只是不明白爲什麼特定的整數寄存器需要在不同的情況下使用。因此,例如,通過試驗和錯誤,我發現當我說出我想要的系統調用時,例如,

mov  rax, 1 
    ... 
    syscall 

我把值1到整數寄存器rax,但我還可以使用整數寄存器eaxaxal,或ah

我還沒有學會很長的組裝,所以它可能是一個明顯的問題。

如果我的問題不明顯:我想知道如何決定將值移動到哪個整數寄存器。如果有這樣的通用系統,或者如果每個不同的意圖使用不同的整數寄存器。

我在64位Ubuntu上使用NASM。

編輯:我的問題是不是this one,重複的,因爲在那裏,一個人的詢問,你會用整數寄存器,我所要求的決定的方法,其整數註冊使用。

+0

寄存器'al','ah'和'ax'來自舊的8位和16位x86架構。 'al'是'ax'的低8位,'ah'是高8位。當i386被引入32位時,'ax'成爲* extended *累加器寄存器'eax'的低16位。然後再將它以64位變量擴展爲'rax'。一個好的英特爾x86程序集歷史搜索應該爲你挖掘出來。或者甚至大多數優秀的教程應該包括我想的。 –

+0

「最好的教程」 - 你能鏈接一個嗎?我使用的教程似乎不是那麼好 –

+0

說實話,我實際上並沒有在很長一段時間看過任何x86(16,32或64位)教程,所以我不幸地不知道哪個存在,哪個好還是不好。這只是一個斷言,因爲我認爲一個好的教程應該在其介紹中有一些歷史。 –

回答

3

程序集或x86機器沒有定義您應該使用哪個通用寄存器(GPR),您可以使用任何可用的GPR(或使其中一個可用),但是,不同的環境爲寄存器使用和參數傳遞定義了不同的約定,當你想使用別人的代碼時,你必須遵守這些慣例。

具體而言,Linux的X86-64利用以下約定,如在X86 psABI描述(第3.2.3節):

  • 如果類INTEGER,下一使用序列%rdi,%rsi,%rdx,%rcx,%r8和%r9的可用寄存器。
  • 如果它是一個標準的用戶級代碼,那是爲rdirsi和在上面的第一個例子rdx選擇的原因,第一參數被傳遞在rdi,第二次在rsi和第rdx

    然而,上述實施例表明系統調用的Linux內核內部調用約定,它類似於有一些不同用戶級應用程序(部分A.2.1):

    1. 用戶級應用程序使用作爲用於傳遞序列%rdi,%rsi,%rdx,%rcx,%r8和%r9的整數寄存器。內核接口使用%rdi,%rsi,%rdx,%r10,%r8和%r9。
    2. 系統調用是通過syscall指令完成的。內核銷燬寄存器%rcx和%r11。
    3. 系統調用的數量必須在寄存器%rax中傳遞。

    正如你可以在樣品中看到的,每個系統調用定義了基於一個Linux System Call Table for x86-64(如由zx485註釋)的RAX值。
    請注意,系統調用可能具有多達6個參數,而不像用戶級代碼不能將堆棧用於其他參數。

    針對Windows,32位或其他環境有不同的ABI,但我不會在這裏詳細介紹它們。

    關於對alaxeax使用您的評論:採用x86-64架構的要求是指定RAX系統調用的數量,使用寄存器的任何其他部分時是基於運氣 - 如果所有寄存器其他部分的位爲零,那麼你可以使用低位 - 但你不應該相信它。
    提醒一下:

    rax is the full 64-bit register 
    eax is the lower 32-bits 
    ax is the lower 16-bits 
    al is the lower 8 bits 
    ah is the value in bits 8 through 15 
    

    正如你可以看到,使用ah是錯誤的,可以調用系統調用不同!

    +0

    請注意,「x64」通常只能在Windows術語中看到。 Linux將其稱爲x86-64或amd64。 (Windows也使用「x86」表示32位,但Linux/SysV術語使用它作爲全部術語來包含所有x86 CPU,以及i386或x86-32(32位)。) –

    +0

    @PeterCordes,編輯:) –

    +0

    哦,我以爲你其實是在談論[x32 ABI](https://en.wikipedia。org/wiki/X32_ABI)作爲另一個ABI:P(長模式中的32位指針)的示例。 –

    相關問題