为什么 NASM 在操作数中没有将有效的指令助记符作为符号名称的问题?



我写了以下简单程序,但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

正如我在此答案时,这是因为str是指令。因此,我在str上添加了一个结肠,现在它可以很好地编译。但是该线

mov rsi, str

str是这里的指令,但仍然可以编译良好。为什么?

正如nasm手册所解释的那样,除了宏定义和指令外,nasm源线的格式具有这四个字段的一定组合:

label:    instruction operands        ; comment

mov视为助记符后,它不再考虑剩余的令牌作为可能的指令助记符。汇编语言严格每句话是一种指令。

如果您想要编码str ax指令的字节作为mov -Sign-Sign-extended-immm32的直接操作数,则必须使用数字常数来执行此操作。 nasm syntax nont可以为您做到这一点,因此,它的解析器一旦找到助记符就不需要反复出现。


或不用手动编码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...

最新更新