Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly DOSBox上的8086组件:带有idiv指令的错误?_Assembly_X86_X86 16_Tasm_Dosbox - Fatal编程技术网

Assembly DOSBox上的8086组件:带有idiv指令的错误?

Assembly DOSBox上的8086组件:带有idiv指令的错误?,assembly,x86,x86-16,tasm,dosbox,Assembly,X86,X86 16,Tasm,Dosbox,我在帮助我的一个朋友调试他的程序,我们把它缩小到了一个甚至在这里也会发生的问题: .MODEL small .STACK 16 .CODE start: mov ax, 044c0h mov bl, 85 idiv bl exit: mov ax, 4c00h int 21h end start 在使用tasm 4.1组装它并在DOSBox 0.74上运行之后,它进入一个无限循环。当使用turbo debugger检查它时,可以看到它发生在idiv指令

我在帮助我的一个朋友调试他的程序,我们把它缩小到了一个甚至在这里也会发生的问题:

.MODEL small
.STACK 16
.CODE
start:
    mov ax, 044c0h
    mov bl, 85
    idiv bl
exit:
    mov ax, 4c00h
    int 21h

end start
在使用tasm 4.1组装它并在DOSBox 0.74上运行之后,它进入一个无限循环。当使用turbo debugger检查它时,可以看到它发生在
idiv
指令之后,该指令出于某种原因修改了
cs
ip
寄存器,并且在两条看似随机的指令将它们恢复到指向
idiv
行之后,再次无限期地执行它


有人对此有什么解释吗?

这个问题是其他部门相关故障的变体。网站还有一些附加链接:

  • idiv
    /
    div
    问题
    :。如果64b/32b=>32b商实际上不适合32b,则32bit
    div
    会出错

调试器似乎跳转到的显然是随机代码的算术异常处理程序(与除以零相同)。发生的情况是,您的代码正在经历
除法溢出
。您正在执行16位/8位。从文件中:

将AX除以r/m8,结果存储在:AL中← 商啊← 剩余的

你会注意到,对于8位除数的除法(在你的例子中是BL),商的范围是-128到+127。044c0h IDIV 85是207(十进制)。207不适合有符号8位寄存器,因此会出现除法溢出和意外问题的原因

要解决这个问题,您可以向上移动16位除数。所以你可以把除数放在BX(16位寄存器)中。那将是
mov bx,85
。不幸的是,事情并非如此简单。当使用16位除数时,处理器假定被除数为32位,DX为高16位,AX为低16位

符号除法DX:AX除以r/m16,结果存储在AX中← 商← 剩余的

要解决此问题,必须对AX中的16位值进行符号扩展。这很简单,因为您只需要在将值放入AX后使用指令。从指令集引用

DX:AX← 斧头的符号

实际上,如果AX的最高有效位(MSB)为0,DX将变为0。如果MSB为1,则DX将变为0ffffh(所有位均设置为1)。数字的符号位是MSB

记住所有这些,您的除法代码可以调整为16位除数:

mov ax, 044c0h
cwd                ; Sign extend AX into DX (DX:AX = 32-bit dividend)
mov bx, 85         ; Divisor is 85
idiv bx            ; Signed divide of DX:AX by BX

因为除法的有符号商不能放入8位寄存器(AL),所以会出现算术溢出。r16/r8上商的范围为−128至+127。你的除法得到的商是207。@MichaelPetch:是的。我正要把这个作为回答,但你打败了我!这将是INT 00h中断处理程序。让我有点惊讶的是,它直接跳回了坏代码,导致了一个无限循环。我本以为它会终止应用程序,打印一条错误消息,或者做一些更明显的事情。在这么多天里,你是第二个对此感到困惑的人。除法溢出与除法为零是相同的例外。您应该设置异常处理,或者使用16位操作防止溢出。当然可以。我没有想到这方面的行动。仍然是新的组装。简单地将它改为一个字除法应该可以解决这个问题吗?相关:有一个表的版本,用于8到64位的所有大小的无符号div。