Почему мы должны устранять двусмысленность при добавлении немедленного значения к значению в адресе памяти


Объясняет , что если мы не зададим оператор размера (например, byte или dword) при добавлении непосредственного значения к значению, хранящемуся в адресе памяти, NASM вернет сообщение об ошибке.

section .data           ; Section containing initialized data

    memory_address: db "PIPPACHIP"

section .text           ; Section containing code

global  _start          ; Linker needs this to find the entry point!

_start:

23            mov ebx, memory_address
24            add [ebx], 32

........................................................

24:  error: operation size not specified. 

- честному.

Мне любопытно, почему это так, однако. Поскольку два следующих сегмента кода дадут один и тот же результат.

add byte [ebx], 32

Или

add dword [ebx], 32

Так какая разница? (Кроме того, что не имеет особого смысла, почему вы используете dword в этом случае). Это просто потому, что "НАСМ так говорит"? Или здесь есть какая-то логика, которой мне не хватает?

Если ассемблер может расшифровать размер операнда из имени регистра, например add [ebx], eax будет работать, почему бы не сделать то же самое для непосредственного значения, т. е. просто пойти вперед и вычислить размер непосредственного значения заранее.

В чем заключается требование это означает, что оператор размера должен быть указан при добавлении немедленного значения к значению в адресе памяти?

NASM версия 2.11.08 Архитектура x86

1 3

1 ответ:

Поскольку два следующих сегмента кода дадут один и тот же результат:

add byte [ebx], 32
add dword [ebx], 32

Они дают только один и тот же результат, потому что 'P' + 32 не переносится в следующий байт.

Флаги устанавливаются в соответствии с результатом. Если бы 4-й байт имел свой высокий бит, то SF был бы установлен для версии dword.

Re: комментарии о том, как работает CF:

Вынос из надстройки всегда 0 или 1. то есть сумма двух N-разрядных целых чисел всегда будет вписываться в (N+1) - битное целое число, где дополнительный бит равен CF. Представьте себе, что add eax, ebx дает результат в CF:EAX, где каждый бит может быть 0 или 1 в зависимости от входных операндов.


Кроме того, если ebx указывает на последний байт на странице, то dword [ebx] может выполнить segfault (если следующая страница не была сопоставлена), но byte [ebx] не будет.

Это также имеет последствия для производительности: чтение-изменение-запись байта не может хранить-вперед к загрузке dword, а dword чтение-изменение-запись обращается ко всем 4 байты.


По этим и другим причинам имеет значение, является ли код операции для инструкции, которую NASM собирает в выходной файл, кодом операции для add r/m32, imm8 или add r/m8, imm8.

Хорошо, что это заставляет вас быть откровенным о том, что вы имеете в виду, вместо того, чтобы иметь какой-то дефолт. Основывать его на размере непосредственного тоже было бы запутанно, особенно при использовании константы ASCII_casebit equ 0x20. Вы не хотите, чтобы размер операнда ваших инструкций изменялся, когда вы меняете константу.