Нет, MOVZX - нулевое расширение, а не знак. И CWD подписывает AX в DX: AX (как вы хотели до I DIV, а не DIV).
movSx eax, word [wNum2]
- более эффективный способ сделать mov ax,mem
+ CWD E , не CWD. (Если известно, что ваши входные данные являются неотрицательными при обработке со знаком, расширение знака и нуля делает одно и то же).
Что делает cltq в сборке? имеет таблицу cbw / cwde / cdqe и эквивалентная инструкция movsx, а также то, что делает cwd / cdq / cqo (и эквивалентный mov / sar).
Ничто из перечисленного не является тем, что вы хотите, прежде чем unsigned div
: используйте xor edx,edx
для обнуления DX, вход старшей половины для 32/16 => 16-битного деления.
См. Также Когда и почему мы подписываем расширение и используем cdq с mul / div?
Чтобы избежать ложных зависимостей от записи частичных регистров, на большинстве последних процессоров наиболее эффективным было бы сделать загрузку movzx, просто чтобы получить 16-битное значение в AX без слияние с предыдущим значением RAX / EAX. Точно так же обнуление по xor (обычно?) Не распознается как идиома обнуления в частичных регистрах, поэтому вам нужен 32-битный размер операнда, даже если вы собираетесь читать только младшую половину
movzx eax, word [wNum2] ; zere extend only to avoid false dep from merging into EAX
xor edx, edx ; high half dividend = DX = 0
div word [wNum3]
mov [wAns16], dx ; store remainder from DX, not EDX
Ваш код, хранящий 32-битный EDX в [wAns16]
, по-видимому, является ошибкой, при условии, что там есть только 2 байта, прежде чем вы наступите на то, что последует за ним.