Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.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 为什么没有';实现t DIV指令以设置CF,而不是引发异常_Assembly_X86_Cpu Architecture_Integer Division_Instructions - Fatal编程技术网

Assembly 为什么没有';实现t DIV指令以设置CF,而不是引发异常

Assembly 为什么没有';实现t DIV指令以设置CF,而不是引发异常,assembly,x86,cpu-architecture,integer-division,instructions,Assembly,X86,Cpu Architecture,Integer Division,Instructions,我知道在组装中进行分割时必须非常小心,即。 这样做: mov ah, 10h mov al, 00h ; dividend = 1000h mov bl, 10h ; divisor = 10h div bl ; Integer overflow exception, /result 100h cannot fit into al 我已经编写了一些可能不支持gotcha的逻辑,为部门创建了一个更友好的环境

我知道在组装中进行分割时必须非常小心,即。 这样做:

          mov ah, 10h
          mov al, 00h ; dividend = 1000h
          mov bl, 10h ; divisor = 10h
          div bl      ; Integer overflow exception, /result 100h cannot fit into al
我已经编写了一些可能不支持gotcha的逻辑,为部门创建了一个更友好的环境:

          mov ah, 10h
          mov al, 00h
          mov bl, 10h 
TryDivide:
          cmp bl,ah
          jna CatchClause
          div bl
          clc
          jmp TryEnd
CatchClause:
          stc
TryEnd:
     

有没有人知道这样的技术原因,没有实现,我们有异常而不是标志集/寄存器被截断?

要得到明确的答案,你必须询问8086指令集的设计者

其他英特尔工程师负责实际实施,但几乎完全由一个人完成。他还被认为是8086的首席建筑师。2008年,为了纪念8086诞生30周年,更重要的是,他写了一本书,《8086/8088入门》(1982)。我没有读过,但显然他讨论了一些设计决策以及如何编程。如果你幸运的话,也许他写了一些关于选择div/idiv陷阱的东西


没有理由非得这样;设置CF和/或OF和截断将是有效的设计。但是,您仍然需要选择一些值,以便将其放入除法为零的情况1中的商/余数输出寄存器中。(我认为对于具有HW除法的ISA来说,对于至少被零除法的ISA,有一个被错误除法的异常是相当常见的,但不幸的是,只提到x86是一个具有陷阱的ISA。如果除法确实存在陷阱,并且POSIX操作系统提供了一个信号,那么算术异常必须是SIGFPE。)

请注意,中的其他ISA会做出不同的选择。例如,ARM division从不出错,也不会设置标志。(虽然它不提供双倍宽度的红利,所以只有和除以0的情况对它来说是特别的。)

IDK如果构建一个硬件除法单元(或微码)来获得溢出情况下的正确截断商(当精确商大于16位时),将比简单地检测溢出和清除更困难。如果是这样,那将是一个相当好的理由

(在输出寄存器和设置标志中保留垃圾是可能的,但不是很好;如果每个除法想要避免使用垃圾,则需要在事后检查结果。)

注1:div by 0在某些方面是这种情况的特例:
high_half
对于除数=0的任何除数都是false。但是没有明确的数学结果可以截断。IEEE FP division通过将除数接近0(即+-无穷大)时的极限处理来解决这一问题。但是整数0应该被假定为精确的0,而不是一个很小的数字,并且没有带内NaN或Inf值可以使用,只有一个有限的0xFFFF


如果考虑标记,则没有其他8086个数学指令需要截断。 请注意,8086仅包括和的一个操作数形式,它们可以执行加宽乘法:
DX:AX=AX*src
。(如果高半部非零(对于
mul
),或者如果高半部不是低半部的符号扩展(对于),则设置CF和OF)。直到后来,CPU才引入了截断形式,如
imul r,r/m,imm
()和
imul r,r/m
(386),它们不会浪费时间在任何地方写入高半音,尽管仍然设置了标志,以便您可以在需要时检测签名换行。(大多数情况下都没有,所以后来的CPU只提供imul,即除标志外其他版本相同的mul。)

add
/
sub
可以进位/借位,但add的完整结果可用作
CF:reg
,进位标志中有额外的位

如果考虑SAR/SHR/<代码> SHL Reg、Cl</Cl>作为位逻辑运算,而不是数学运算,则它不计数,即使它可以移出多个位而不会将它们留在任何地方。(最后一位保留在CF中,因此可以通过旋转进位撤消移位1。)

这使得DIV/IDIV成为唯一可能有更广泛结果且无处放置的算术指令。这可能是选择让它们出错的部分动机


high_-half
是无符号除法的证明 这就是商适合操作数大小的确切条件
1:0
(例如,对于8位操作数大小,
0x0100
)是不适合的最小商,因此
0x0100*除数
是产生不适合8位的商的最小红利

当被分成与被除数相同宽度的hi:lo两半时,该被除数为除数:0

任何小于该值的数字都必须从高半部“借用”,使其严格小于除数


(签名除法也有
INT_MIN/-1
溢出角的情况,高半部检查可能必须是绝对值。)

这个问题可能更适合于。这似乎是离题了,因为它正在寻找硬件设计决策的基本原理。我认为检查实际上是有证据的
high_half
是商适合无符号除法的确切条件,包括排除零除法。(带符号的除法也有
INT_MIN/-1
溢出角的情况,高半检查可能必须是绝对值。)注意,其他ISA做出了不同的选择;例如,ARM截断而不是引发异常。(我假设设置了标志)@彼得科德斯:手臂上的除法(32和64)从不设置旗帜。没有缩小的界限,所以它溢出的唯一方法是有符号的
INT_MIN/-1
,它实际上是无声地包装到
INT_MIN
。这类似于高级语言中的“我应该返回错误代码还是抛出异常”辩论。IDIV:9100h/92h->exception呢,9200h/91h->也有例外?@tinmanjk:我没有对
idiv做出任何明确的声明