ecx
— 32-битный регистр, двойное слово (двойное слово); в терминологии x86 слово WORD имеет размер 2 байта.
Когда вы пытались:
sub ecx, num1 ;ecx = ecx - num1
Ассемблер проверил метку num1
и обнаружил, что она имеет тип word
, поэтому попытался сгенерировать
sub ecx, word ptr [num1] ;ecx = ecx - num1
но такого кода операции не существует.
Форма sub r32, r/m32
sub
существует, но загрузка 4 байтов из 2-байтовой переменной вызовет 2 байта мусора в старшей половине.
sub ecx, dword ptr [num1] ; don't *just* change to this
Это будет собрано, но вам нужно заменить num1
на двойное слово, чтобы оно было правильным. (Если вы не хотите также читать любые 2 байта, которые вы собрали после num1, в свой раздел .data). И если вы используете num1 dword 0FEEDh
, MASM sub ecx, num1
будет работать, потому что он определит правильный размер операнда памяти. Если вы хотите, чтобы MASM проверял размеры ваших переменных по тому, как вы их используете, не используйте переопределения размера операнда, если они вам не нужны (например, чтобы скопировать 4 байта сразу из строки).
Ассемблер рекомендует решить проблему, сделав num1
переменной типа dword или заменив ecx
на cx
. Это не так (cx
не может сохранить вашу константу, но masm
этого не знает); однако есть еще одна возможность. Вы можете выполнить нулевое расширение до рабочего регистра и вычесть это:
movzx edx, num1 ; zero-extending load from a byte or word var
sub ecx, edx
Или, если num1
является подписанным (masm
имеет SWORD
, но я обычно вижу, что WORD
используется как для подписанного, так и для беззнакового):
movsx edx, num1 ; sign-extending load
sub ecx, edx
sub ecx, byte num1
не существует! Кодировкиsub r32, m8
нет. Может быть, вы перепуталиsub r/m32, imm8
с расширенным знаком immediate? Единственными скалярными целочисленными инструкциями x86, которые выполняют загрузку со знаком или нулем, являютсяmovsx
иmovzx
, другим инструкциям требуется, чтобы их операнд в памяти был той же ширины, что и размер операнда.@PeterCordes: Подождите, я проверю, что сгенерировал
nasm
, когда он успешно собрал это.Обратите внимание, что это вопрос MASM, где
sub ecx, word ptr num1
— операнд источника памяти. В NASMsub ecx, byte num1
просто предлагает ассемблеру использовать imm8 для кодирования адреса. Фактическая эквивалентная инструкция NASM —sub ecx, byte [num1]
, которая не ассемблируется. (Помните, что имена простых символов являются операндами памяти в MASM и адресами в NASM).@PeterCordes: Да, я только что понял, что облажался.
Когда вы исправите это, я думаю, также важно использовать синтаксис MASM повсюду; тем более, что
mov eax, word [foo]
действительно собирается в MASM, аword
расширяется до числа 2, поэтому становитсяmov eax, [foo+2]
, что безумно непрозрачно и сбивает с толку новичков, которые не до конца понимают, что делаетword ptr
, не говоря уже о MASM против NASMword ptr
противword
.@PeterCordes: я думаю, что везде использовал синтаксис masm и случайно передал синтаксис masm в nasm.
Нет, как я уже сказал, MASM требует
word ptr
в качестве спецификатора размера операнда для операнда памяти. Я отредактировал, чтобы исправить это для вас.