我编写了以下简单程序,但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
是一个指令助记符,但它仍然编译好。为什么?
答案 0 :(得分:2)
作为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...