我有以下两个代码段:
mov ax, word [wNum2]
cwd
div word [wNum3]
mov [wAns16], dx
movzx eax, word [wNum2]
;cwd
div word [wNum3]
mov [wAns16], edx
第一个会给出正确的答案,第二个会给我一个大约一百左右的答案,除非我取消对cwd的注释。
我的问题是我认为movzx会为我将所有内容归零,这将使cwd不再需要。我是否完全误解了它们的工作原理?有人可以引导我浏览这些代码片段吗?
裸结果可以相等还是不相等-取决于值。CWD状态的描述
通过符号扩展将寄存器AX,EAX或RAX中操作数的大小加倍(取决于操作数大小),并将结果分别存储在寄存器DX:AX,EDX:EAX或RDX:RAX中。CWD指令将AX寄存器中值的符号(位15)复制到DX寄存器中的每个位位置。
因此,如果in的值AX
小于32,767(最大15位),则其结果等效于MOVZX
(零扩展)和MOVSX
(符号扩展)。但是,如果该值更大,则仅等于MOVSX
。通常MOVZX
将与DIV
(无符号除法)结合使用,并与(有符号除法)MOVSX
结合使用IDIV
。
但是仍然存在将结果存储在何处的问题:
CWD
将32位结果存储在两个16位寄存器中DX:AX
,而MOV?X
指令将其存储在32位寄存器中EAX
。
这对以下DIV
指令有影响。代码的第一部分使用32位值DX:AX
作为输入,而第二种方法假定EAX
为16位的输入DIV
:
F7 /6 DIV r/m16 M Valid Valid Unsigned divide DX:AX by r/m16, with result stored in AX ← Quotient, DX ← Remainder.
这使得结果不可预测,因为它DX
是不确定的,并且EAX
除法的上半部分未被使用。
您可能应该提到,您通常希望在()之前零扩展,而仅在之前进行符号扩展。 我们什么时候以及为什么要签署extend,并在mul / div中使用cdq?而为什么要EDX使用DIV指令之前为0?
div
xor edx,edx
idiv