如何知道要使用哪个整数寄存器

时间:2017-08-29 15:48:32

标签: assembly x86 nasm x86-64 cpu-registers

我试图学习装配,这在某种程度上是有意义的,但我有一个问题。我有这个源文件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或{ {1}}。

我还没有长时间学习装配,所以很可能是一个显而易见的问题。

如果我的问题不明显:我想知道如何决定将值移到哪个整数寄存器,例如如果有一些通用系统,或者每个不同意图使用不同的整数寄存器。

我在64位Ubuntu上使用NASM。

修改:我的问题与this one,不重复,因为在那里询问您将使用较小的整数寄存器的位置,我和#39; m要求一种方法来决定使用哪个整数寄存器。

1 个答案:

答案 0 :(得分:3)

汇编或x86机器没有定义您应该使用的通用寄存器(GPR),您可以使用任何可用的GPR(或使其可用),但是,不同的环境定义了寄存器使用和参数的不同约定通过,当你想要使用他人时#39;代码你必须遵守这些约定。

具体来说,Linux x86-64正在使用以下约定,如X86 psABI(第3.2.3节)中所述:

  
      
  1. 如果该类为INTEGER,则使用序列%rdi,%rsi,%rdx,%rcx,%r8和%r9的下一个可用寄存器。
  2.   

如果是标准的用户级代码,那就是在上面第一个示例中选择rdirsirdx的原因,第一个参数是传入的rdirsi中的第二个,rdx中的第三个。

但是,上面的例子演示了syscalls的Linux内核调用约定,它类似于用户级应用程序,但有一些区别(第A.2.1节):

  
      
  1. 用户级应用程序使用整数寄存器来传递序列%rdi,%rsi,%rdx,%rcx,%r8和%r9。内核接口使用%rdi,%rsi,%rdx,%r10,%r8和%r9。
  2.   
  3. 系统调用通过syscall指令完成。内核会破坏寄存器%rcx和%r11。
  4.   
  5. 系统调用的号码必须在寄存器%rax中传递。
  6.   

正如您在示例中所看到的,每个系统调用都根据Linux System Call Table for x86-64定义了rax值(由zx485评论)。
请注意,系统调用可能有最多6个参数,与用户级代码不同,不能使用堆栈来获取其他参数。

Windows有不同的ABI,32位或其他环境,但我不会在这里详细说明。

关于您对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是错误的,可能会调用另一个系统调用!