从 64 位 nasm 代码接收 32 位寄存器

the*_*ang 5 assembly x86-64 nasm cpu-registers

我正在学习 64 位 nasm,我通过执行以下操作来汇编 .nasm 文件,该文件仅包含 64 位寄存器

nasm -f elf64 HelloWorld.nasm -o HelloWorld.o
Run Code Online (Sandbox Code Playgroud)

并链接它执行以下操作

ld HelloWorld.o -o HelloWorld
Run Code Online (Sandbox Code Playgroud)

程序运行正确,甚至在我运行命令时说它是 64 位 ELF file,但是当我使用objdumpgdb反汇编可执行文件时,我在代码中作为 64 位寄存器放置的寄存器在以下情况下显示为 32 位寄存器:已拆卸。(示例:rax在源代码中显示为eax反汇编时的样子)

为什么是这样?

这种情况不仅仅发生在一台计算机上,而且这是一个新问题,以前没有这样做过。

你好世界.nasm:

global _start

section .text

_start:
        mov rax, 1
        mov rdi, 1
        mov rsi, hello_world
        mov rdx, length
        syscall

        mov rax, 60
        mov rdi, 11
        syscall

section .data

        hello_world: db 'Hello World',0xa
        length: equ $-hello_world
Run Code Online (Sandbox Code Playgroud)

拆解后的HelloWorld:

...
00000000004000b0 <_start>:
  4000b0:       b8 01 00 00 00          mov    eax,0x1
  4000b5:       bf 01 00 00 00          mov    edi,0x1
  4000ba:       48 be d8 00 60 00 00    movabs rsi,0x6000d8
  4000c1:       00 00 00
  4000c4:       ba 0c 00 00 00          mov    edx,0xc
  4000c9:       0f 05                   syscall
  4000cb:       b8 3c 00 00 00          mov    eax,0x3c
  4000d0:       bf 0b 00 00 00          mov    edi,0xb
  4000d5:       0f 05                   syscall
...
Run Code Online (Sandbox Code Playgroud)

And*_*ter 7

为什么

...
mov rax, 1
mov rdi, 1
mov rsi, hello_world
...
Run Code Online (Sandbox Code Playgroud)

被拆解为

...
4000b0:       b8 01 00 00 00          mov    eax,0x1
4000b5:       bf 01 00 00 00          mov    edi,0x1
4000ba:       48 be d8 00 60 00 00    movabs rsi,0x6000d8
4000c1:       00 00 00
...
Run Code Online (Sandbox Code Playgroud)

因为文字0x1适合 32 位,并且当通过相应的寄存器加载低 32 位时,64 位寄存器的高 32 位被设置为0E。因此汇编器可以优化mov为 32 位操作。

请注意,加载的地址rsi可能不适合 32 位,因此rsi保持原样。

如果加上下面的指令,就可以很清楚的看到效果:

mov rbx, 0x0ffffffff      ; still fits into 32 bit
mov rbx, 0x100000000      ; does not fit into 32 bits anymore
Run Code Online (Sandbox Code Playgroud)

被拆解为

 a: bb ff ff ff ff          mov    $0xffffffff,%ebx
 f: 48 bb 00 00 00 00 01    movabs $0x100000000,%rbx
16: 00 00 00 
Run Code Online (Sandbox Code Playgroud)

您可以使用 禁用 nasm 优化-O0,在这种情况下,指令将保留其长格式:

nasm -O0 -f elf64 HelloWorld.asm 
Run Code Online (Sandbox Code Playgroud)

结果:

14: 48 bb ff ff ff ff 00    movabs $0xffffffff,%rbx
1b: 00 00 00 
1e: 48 bb 00 00 00 00 01    movabs $0x100000000,%rbx
25: 00 00 00 
Run Code Online (Sandbox Code Playgroud)