Сборка x86 imul и div не делают то, что я ожидаю - PullRequest
0 голосов
/ 31 января 2020

Когда я go делю, это дает мне некоторые из этого мира ответы. Это работает:

mov ax, 11
mov bl, 37
div bl
mov [bAns16], ah

И даст мне правильный остаток от 11. Но как только я переключу эти числа на переменные, все обрывается:

mov ax, [bNum1]
mov bl, [bNum4]
div bl
mov [bAns16], ah


;bNum1 = 11
;bNum4 = 37

Ответ должен быть 0 с остатком 11. Но ответ заканчивается 104 и как-то с остатком 3.

Более того, у меня проблемы с использованием imul - вообще не имеет смысла. То же, что и с div:

mov ax, 33
mov bx, -17
imul ax, bx
mov [wAns15], ax

Даст мне правильный ответ, но не будет, как только я добавлю туда переменные:

mov ax, [bNum5]
mov bx, [bNum6]
imul ax, bx
mov [wAns15], ax

;bNum5 = 33
;bNum6 = -17

Так что оно должно равняться -561, но дает мне -32049 вместо этого последовательно.

Что я делаю не так? Спасибо!

РЕДАКТИРОВАТЬ:

Вот объявления номера:

bNum1       db  11
bNum2       db  15
bNum3       db  26
bNum4       db  37
bNum5       db  33
bNum6       db  -17
bNum7       db  -29
bNum8       db  -40

Ответы [ 2 ]

4 голосов
/ 31 января 2020

AX и BX - 16-битные регистры. mov ax, [bNum1] будет читать 16 бит (два байта) из bNum1. Но поскольку [bNum1] (0x0B) - это только один байт, он также будет читать [bNum2] (0x0F) как старший байт. Поэтому после mov ax, [bNum1] AX это не 11, а 3851 (0x0F0B).

2 голосов
/ 31 января 2020

Ответ должен быть 0 с остатком 11. Но ответ заканчивается 104 и как-то с остатком 3.

Это означает, что AX содержал значение 0x0F0B вместо 0x000B перед инструкцией div.

W. Комментарий Чанга подразумевает причину этого:

В отличие от языков программирования более высокого уровня (таких как C), язык ассемблера позволяет центральному процессору напрямую что делать.

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

Ваша "переменная" bNum1 имеет длину в один байт. Это будет переменная типа unsigned char на языке программирования C.

Однако инструкция mov ax, [bNum1] будет обращаться к двухбайтовому значению в памяти. Это равняется типу данных unsigned short в C.

Эта инструкция будет интерпретировать два байта, хранящиеся по адресу bNum1, и адрес, следующий за этим адресом, как один 16-битный число.

Байт по адресу bNum1 равен 11, а байт по адресу, следующему за этим адресом (bNum2), равен 15; эти два байта будут интерпретироваться как 0xF0B.

Что делать

W. Чанг уже рекомендовал использовать dw вместо db.

На языке программирования C это приведет к изменению типа данных переменной bNum1 с unsigned char на unsigned short.

Однако вы, возможно, не захотите менять тип данных.

В этом случае вам потребуется преобразовать 8-разрядное число в 16-разрядное:

For беззнаковых чисел это просто делается путем установки старших 8 битов в ноль.

Для знаковых чисел процессоры x86 имеют инструкции с именем cbw (от 8 до 16 бит) и cwd (от 16 до 32 бит). К сожалению, это работает только с регистром AX.

В следующих примерах показано, как 8-разрядное число в AL преобразуется в 16-разрядное число в AX:

Без подписи:

mov al, [bNum1]
mov ah, 0

Подпись:

; You want to load bNum6 to BX ...
mov al, [bNum6]
cbw
mov bx, ax
; ... and bNum5 to AX
mov al, [bNum5]
cbw
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...