我正在尝试编写一个简单的汇编程序,将1000除以5,但我的程序会冻结系统.
该计划如下,
include pcmac.inc
.model Small
.586
.stack 100h
.data
const db 5
Main PROC
_Begin
mov AX, 1000
idiv const // Problem line
_Exit 0
Main ENDP
End Main
Run Code Online (Sandbox Code Playgroud)
如果我使用无符号除法div而不是有符号除法,问题就会消失idiv.
有谁能解释为什么?
我知道分裂的唯一条件是股息必须是除数的两倍.还有其他我想念的东西吗?
const是一个字节.当你这样做时IDIV byte_divisor,商将被放入AL,并且范围为-128到127. 1000/5是200,这不在允许的范围内.如果使用DIV,则商的范围是0到255,这就是为什么您的示例在这种情况下有效.
如果你想要IDIV1000乘5,你应该使用16位除数.但是你需要记住,在使用时IDIV r/m16,你实际划分的是32位双字组成DX和AX(DX保持最高有效位和AX最低有效位).
来自英特尔的手册:
IDIV r/m16 Signed divide DX:AX by r/m16, with result stored in AX ? Quotient, DX ? Remainder.
IF OperandSize = 16 (* Doubleword/word operation *)
THEN
temp ? DX:AX / SRC; (* Signed division *)
IF (temp > 7FFFH) or (temp < 8000H)
(* If a positive result is greater than 7FFFH
or a negative result is less than 8000H *)
THEN
#DE; (* Divide error *)
ELSE
AX ? temp;
DX ? DX:AX SignedModulus SRC;
Run Code Online (Sandbox Code Playgroud)
所以在IDIV你应该DX:AX从值中创建一个有符号的双字之前AX.有一个命名指令CWD正是这样做的:
该
CWD指令将AX寄存器中值的符号(第15位)复制到寄存器中的每个位DX.
即:
.data
const dw 5 ; now a word
.code
mov ax,1000
cwd ; sign-extend ax into dx
idiv const
; quotient is in ax, remainder in dx
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1222 次 |
| 最近记录: |