Почему мы должны устранять двусмысленность при добавлении немедленного значения к значению в адресе памяти
Объясняет , что если мы не зададим оператор размера (например, 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 ответ:
Поскольку два следующих сегмента кода дадут один и тот же результат:
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
. Вы не хотите, чтобы размер операнда ваших инструкций изменялся, когда вы меняете константу.