Почему у 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 здесь является мнемоникой инструкции, но все равно компилируется нормально. Почему?


person St.Antario    schedule 07.12.2017    source источник
comment
nasm рассматривает 'str' явно как метку и, таким образом, не жалуется. std db 'some string' является синтаксической ошибкой, это уже найдено на шаге 1, задолго до того, как кто-то попытается разрешить метку str   -  person Tommylee2k    schedule 07.12.2017
comment
К сожалению, извините, вы спрашиваете, почему он не компилируется. Не дубликат. Вероятно, ваш голос привлек мое внимание к этому старому ответу, прежде чем я посмотрел на это: P   -  person Peter Cordes    schedule 07.12.2017
comment
можно даже использовать mov rsi, mov и mov: db 'something' и nasm не будет жаловаться   -  person Tommylee2k    schedule 07.12.2017


Ответы (1)


Как объясняется в руководстве по NASM, помимо определений макросов и директив, формат 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...
person Peter Cordes    schedule 07.12.2017