将内容从 .data 部分移动到 NASM 中的寄存器

Moving contents from .data section to register in NASM

我是 NASM 的新手,很难将变量的内容从 .data 部分移动到寄存器。以下代码输出 "Value: 0" 而不是 "Value: 1"。如果我写常量直接注册(mov qword rax, 25)一切正常。

; /usr/local/bin/nasm -f macho64 sum.asm && ld -macosx_version_min 10.7.0 -lSystem -o sum sum.o && ./sum


section .data
myvar: dq 1234
message: db "Value: %i", 10, 0
.len:   equ     $ - message


global start

extern _printf
extern _exit

section .text
start:
    default rel

    ; This outputs "Value: 0"
    mov qword   [myvar], 1
    mov         rax, [myvar]

    ; This works:
    ; mov qword rax, 25


    ; Output
    mov rsi, rax                    


    mov qword   rax, 0                              
    lea         rdi, [rel message]
    call        _printf


    mov qword   rax, 0
    call        _exit

/usr/local/bin/nasm -v 说: NASM version 2.11.08 compiled on Mar 10 2015

您的代码是正确的,除了全局入口点 main 是必需的(但不是必需的,您可以调整入口点 -- 使用 link 选项)。您在这里 link 使用 libc printfexit 函数。虽然编译器不同,但使用 printf 而不是 _printf 会有所帮助。

仅进行这些语义更改(并在 Linux 而不是 Mac 上编译),您的代码将提供所需的输出:

section .data
myvar: dq 1234
message: db "Value: %i", 10, 0
.len:   equ     $ - message

global main

extern printf
extern exit

section .text

main:
    default rel

    ; This outputs "Value: 0"
    mov qword   [myvar], 1
    mov         rax, [myvar]

    ; Output
    mov rsi, rax

    mov qword   rax, 0
    lea         rdi, [rel message]
    call        printf

    mov qword   rax, 0
    call        exit

编译

$ nasm -felf64 -o obj/label64.o label64.asm
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib64/crt1.o \
/usr/lib64/crti.o  obj/label64.o /usr/lib64/crtn.o -lc -o bin/label64

输出

$ ./bin/label64
Value: 1

注意:您可能需要调整link命令所需的路径。否则,您可以只调用 gcc 并让它对路径进行排序。例如:

$ gcc -o bin/label64 obj/label64.o

再次来袭。使用旧版本(如 2.11.06),或修复数据部分中相对符号寻址的新版本。或者使用 yasm.


正如我在评论中所说,您可以使用 xor eax, eax 将 64 位寄存器归零。这是标准的成语。

写入 32 位寄存器 总是 清除 64 位寄存器的 upper32。与移动 64 位立即数相比,这节省了大量指令字节。

mov  qword rax, 25

依然是32bit立即数移动。 qword 是不必要的。该指令确实有一个不需要的 REX 前缀使其成为 64 位写入,而不是通过写入低 32 位自动清除高 32 位。

mov    eax, 25

做同样的事情,但指令字节更少。