为什么 NASM 不能将有效的指令助记符作为操作数中的符号名称?

Why doesn't NASM have trouble with valid instruction mnemonics as symbol names in operands?

我写了下面这个简单的程序,但是nasm拒绝编译。

section .text
    global _start

_start:
    mov rax, 0x01 
    mov rdi, 0x01
    mov rsi, str
    mov rdx, 0x03
    syscall

    mov rax, 60
    syscall

segment .data
    str db 'Some string'


nasm -f elf64 main.asm
main.asm:15: error: comma, colon, decorator or end of line expected after operand

正如我读到的 answer 这是因为 str 是一个指令助记符。所以我在 str 中添加了一个冒号,现在它可以正常编译了。但是这条线呢

mov rsi, str

str 是这里的指令助记符,但它仍然可以正常编译。为什么?

the NASM manual explains 一样,除了宏定义和指令之外,NASM 源代码行的格式包含以下四个字段的某种组合:

label:    instruction operands        ; comment

mov视为助记符后,不再将剩余的标记视为可能的指令助记符。汇编语言严格来说是一条指令一条语句。

如果你想要编码 str ax 指令的字节作为 mov-sign-extended-imm32 的直接操作数,你必须自己做一个数字常量。 NASM 语法没有办法为你做到这一点,所以它的解析器不需要在找到助记符后递归到操作数中。


或者不用手动编码 str,而是使用 db 发出 mov 指令的字节。

db 0x48, 0xc7, 0xc6    ; REX.W prefix, opcode for mov r/m64,imm32,  ModR/M = rsi destination
      str  [rax+1]     ; a disp8 makes this 4 bytes long.


;; same machine code as
mov rsi, strict dword 0x0148000f    ; str [rax+1]

;; nasm optimizes it to mov esi, imm32 without strict dword.
;; I guess I should have used that 5-byte instruction for the DB version...