idiv bx => Error: Division by zero
(ax = 65535 [т.е. -1], bx = 1)
В чём проблема? Почему не получается разделить -1 на 1?
Команда idiv bx работает так:
ax = ax div bx
dx = ax mod bx
Получается, что не совсем так?
Assm - Деление
-
lxa85
Re: Assm - Деление
ManHack, а можно весь кусок кода?
Все, нашел ошибку!
При делении на BX(а BX - это слово) Операнд(т.е. делимое) должно быть двойным словом.
Т.е. находится в DX:AX
Тогда будет возможно деление в пределах -32,768 / +32,767
Что содержит DX до начала операции?
Кусок из
BYTE1 DB 80H ;Data items
BYTE2 DB 16H
WORD1 DW 2000H
WORD2 DW 0010H
WORD3 DW 1000H
;--------------
E10IDIV PROC
MOV AX,WORD1 ;Слово / байт
IDIV BYTE1 ; остаток:частное в AH:AL
MOV AL,BYTE1 ;Байт / байт
CBW ; расширить делимое в AH
IDIV BYTE3 ; остаток:частное в AH:AL
MOV DX,WORD2 ;Двойное слово / слово
MOV AX,WORD3 ; делимое в DX:AX
IDIV WORD1 ; остаток:частное в DX:AX
MOV AX,WORD1 ;Слово / слово
CWD ; расширить делимое в DX
IDIV WORD3 ; остаток:частное в DX:AX
RET
E10DIV ENDP
Что за среда разработки? Фраза "деление на ноль" все же настораживает. Т.е. ИМХО сигнализируется неправильная ошибка.
Операция idiv документация Intel
Все, нашел ошибку!
При делении на BX(а BX - это слово) Операнд(т.е. делимое) должно быть двойным словом.
Т.е. находится в DX:AX
Тогда будет возможно деление в пределах -32,768 / +32,767
Что содержит DX до начала операции?
Кусок из
Питера Абеля
читать дальше »
BYTE1 DB 80H ;Data items
BYTE2 DB 16H
WORD1 DW 2000H
WORD2 DW 0010H
WORD3 DW 1000H
;--------------
E10IDIV PROC
MOV AX,WORD1 ;Слово / байт
IDIV BYTE1 ; остаток:частное в AH:AL
MOV AL,BYTE1 ;Байт / байт
CBW ; расширить делимое в AH
IDIV BYTE3 ; остаток:частное в AH:AL
MOV DX,WORD2 ;Двойное слово / слово
MOV AX,WORD3 ; делимое в DX:AX
IDIV WORD1 ; остаток:частное в DX:AX
MOV AX,WORD1 ;Слово / слово
CWD ; расширить делимое в DX
IDIV WORD3 ; остаток:частное в DX:AX
RET
E10DIV ENDP
Что за среда разработки? Фраза "деление на ноль" все же настораживает. Т.е. ИМХО сигнализируется неправильная ошибка.
-
ManHack
Re: Assm - Деление
Код:
dx на момент выполнения команды idiv содержит ноль.
Среда Turbo Assembler (ассемблер для Intel-совместимых, втроенный в Turbo Pascal 7.0)
Т.е. всегда делится содержимое пары DX:AX на BX?
Или в каких-то случаях делится только содержимое AX на BX? (в каких?)
А каким образом вообще производится деление пары?
Допустим, в AX у меня записано 12, а в DX записано 7, что тогда будет в BX?
А что будет в BX, если в DX записано 65535, а в AX, допустим, 3?
Мне просто интересно как формируется одно число из этой пары DX:AX.
А ещё я видел, что некоторые пишут три регистра после idiv. Например, так:
idiv eax, eax, ah
У меня среда ругается, если я записываю больше одного слова.
Как объясняется этот феномен?
Код: Выделить всё
var
a, b, c, ans : integer;
begin
readln(a, b, c);
asm
mov bx, b
mov ax, c
imul bx
neg ax
mov cx, a
add ax, cx
mov cx, c
sub bx, cx
idiv bx
mov ans, ax
end;
writeln('Value = ', ans);
readln;
end.dx на момент выполнения команды idiv содержит ноль.
Среда Turbo Assembler (ассемблер для Intel-совместимых, втроенный в Turbo Pascal 7.0)
Т.е. всегда делится содержимое пары DX:AX на BX?
Или в каких-то случаях делится только содержимое AX на BX? (в каких?)
А каким образом вообще производится деление пары?
Допустим, в AX у меня записано 12, а в DX записано 7, что тогда будет в BX?
А что будет в BX, если в DX записано 65535, а в AX, допустим, 3?
Мне просто интересно как формируется одно число из этой пары DX:AX.
А ещё я видел, что некоторые пишут три регистра после idiv. Например, так:
idiv eax, eax, ah
У меня среда ругается, если я записываю больше одного слова.
Как объясняется этот феномен?
-
lxa85
Re: Assm - Деление
Среда разработки Lazarus. Все выполнилось не чихнув.
Давай смотреть входные данные.
BTW, а проще конструкции задать нельзя? Больно много действий перед idiv, что усложняет подготовку тестов.
Код:
Давай смотреть входные данные.
BTW, а проще конструкции задать нельзя? Больно много действий перед idiv, что усложняет подготовку тестов.
Код:
Код: Выделить всё
program Project1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils
{ you can add units after this };
var
a, b, c, ans : integer;
{$IFDEF WINDOWS}{$R Project1.rc}{$ENDIF}
{$ASMMODE intel}
begin
// readln(a, b, c);
a:=1;b:=2;c:=7;
asm
mov bx, b
mov ax, c
imul bx
neg ax
mov cx, a
add ax, cx
mov cx, c
sub bx, cx
idiv bx
mov ans, ax
end;
end.-
ManHack
Re: Assm - Деление
Моя программа призвана вычислять выражение (a - b*c)/(b - c), но достаточно разобраться как просто делить -1 на 1 (или что-то подобное), когда деление происходит пары чисел DX:AX?
И всё-таки, что насчёт конструкций вида " idiv eax, eax, ah "? Они вообще реальны? Как они работают и при каких условиях? Что-то толком про такой вариант использования idiv нигде не нашёл, ни у Юрова, ни у Абеля...
И всё-таки, что насчёт конструкций вида " idiv eax, eax, ah "? Они вообще реальны? Как они работают и при каких условиях? Что-то толком про такой вариант использования idiv нигде не нашёл, ни у Юрова, ни у Абеля...
-
DillerInc
Re: Assm - Деление
Цитата ManHack:
И всё-таки, что насчёт конструкций вида " idiv eax, eax, ah "?
...такой конструкции нет.Подобная есть только для умножения.
И теперь такой вопрос: почему в наше время, когда на дворе уже вовсю разгуливает 64-битный код, народ так и норовит использовать 16-битные регистры без надлежащей необходимости?
Код:
И всё-таки, что насчёт конструкций вида " idiv eax, eax, ah "?
Assm - Деление
...такой конструкции нет.Подобная есть только для умножения.
И теперь такой вопрос: почему в наше время, когда на дворе уже вовсю разгуливает 64-битный код, народ так и норовит использовать 16-битные регистры без надлежащей необходимости?
Код:
Код: Выделить всё
asm
mov eax, -1 ; Загружаем в EAX делимое
cdq ; Заполняем EDX знаковым битом регистра EAX
mov ecx, 01 ; Загружаем в ECX делитель
idiv ecx ; Делим
end;
Результат:
EAX == -1
EDX == остаток от деления == 0-
ManHack
Re: Assm - Деление
Необходимость исходит в виде требований свыше ничего кроме ax, bx, cx и dx не использовать ^^
Но за код спасибо. Теперь я знаю, что мне нужна команда cwd.
Но за код спасибо. Теперь я знаю, что мне нужна команда cwd.