2017-08-29 133 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位指针)的示例。 –

    相关问题