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 为什么在使用DIV指令之前EDX应该为0?_Assembly_X86_Integer Division - Fatal编程技术网

Assembly 为什么在使用DIV指令之前EDX应该为0?

Assembly 为什么在使用DIV指令之前EDX应该为0?,assembly,x86,integer-division,Assembly,X86,Integer Division,我注意到,当EDX包含一些随机的默认值,如00401000,然后我使用如下的DIV指令: mov eax,10 mov ebx,5 div ebx 它会导致整数溢出错误。但是,如果我将edx设置为0,并执行相同的操作,它就会工作。我相信使用div将导致商覆盖eax,其余部分覆盖edx 获取这个整数溢出错误确实让我感到困惑。DIV指令将EDX:EAX除以DIV指令后面的r/m32。因此,如果未能将EDX设置为零,则使用的值将变得非常大 信任有助于做什么 对于32位/32位=>32位除法:零或符号

我注意到,当EDX包含一些随机的默认值,如00401000,然后我使用如下的DIV指令:

mov eax,10
mov ebx,5
div ebx
它会导致整数溢出错误。但是,如果我将
edx
设置为0,并执行相同的操作,它就会工作。我相信使用
div
将导致商覆盖
eax
,其余部分覆盖
edx


获取这个整数溢出错误确实让我感到困惑。

DIV指令将EDX:EAX除以DIV指令后面的r/m32。因此,如果未能将EDX设置为零,则使用的值将变得非常大

信任有助于

做什么 对于32位/32位=>32位除法:零或符号,将32位红利从EAX扩展到64位EDX:EAX。
对于16位,将AX转换为DX:AX,使用
cwd
或异或调零

  • 无符号:
    XOR EDX,EDX
    然后
    DIV除数
  • 签名:
    CDQ
    然后
    IDIV除数
另见


为什么(TL;DR) 例如,寄存器
EDX
EAX
形成一个单独的64位值(通常显示为
EDX:EAX
),在这种情况下,该值被
EBX
除以

因此,如果
EAX
=
10
或hex
A
EDX
是,比如说
20
或hex
14
,那么它们一起形成64位值hex
14 0000 000A
或十进制
85899345930
。如果除以
5
,则结果为
17179869186
或十六进制
4 0000 0002
这是一个不适合32位的值

这就是为什么会出现整数溢出。

但是,如果
EDX
仅为
1
,则将十六进制
1 0000 000A
除以
5
,结果为十六进制
3333 3335
。这不是您想要的值,但不会导致整数溢出

要将32位寄存器
EAX
除以另一个32位寄存器,请注意由
EDX:EAX
形成的64位值的顶部为
0

因此,在进行单个除法之前,通常应将
EDX
设置为
0

(或对于签名部门,
cdq
签名将
EAX
扩展到
EDX:EAX
之前的
idiv


但是
EDX
不一定总是
0
。结果可能不会太大,导致溢出

my
BigInteger
code中的一个示例:

在用
DIV
除法后,商在
EAX
中,余数在
EDX
中。要将由多个
DWORDS
组成的
BigInteger
数组除以
10
(例如将值转换为十进制字符串),请执行以下操作:

    ; ECX contains number of "limbs" (DWORDs) to divide by 10
    XOR     EDX,EDX      ; before start of loop, set EDX to 0
    MOV     EBX,10
    LEA     ESI,[EDI + 4*ECX - 4] ; now points to top element of array
@DivLoop:
    MOV     EAX,[ESI]
    DIV     EBX          ; divide EDX:EAX by EBX. After that,
                         ; quotient in EAX, remainder in EDX
    MOV     [ESI],EAX
    SUB     ESI,4        ; remainder in EDX is re-used as top DWORD... 
    DEC     ECX          ; ... for the next iteration, and is NOT set to 0.
    JNE     @DivLoop
在该循环之后,由整个数组(即由
biginger
表示)表示的值除以
10
,并且
EDX
包含该除法的剩余部分


FWIW,在我使用的汇编器(Delphi的内置汇编器)中,以
@
开头的标签是函数的本地标签,即它们不会干扰其他函数中同名的标签。

这就是指令的定义/实现方式-对于32位操作数,它将edx:eax中的64位值除以32位操作数值。如果要将64位数字除以32位数字,则必须在开始之前设置所有64位,否则结果将毫无意义。该链接来自。对于处理asm的人来说,这里有很多好东西。在使用不熟悉的操作码之前,最好先看一下指令参考相关:8位操作数大小是一种特殊情况:
div bl
(16b/8b=>8b),使用AX(而不是DL:AL)。对于“为什么我的坏除法代码不起作用”FAQ,这可能是比我标记的重复代码更好的标准答案。我做了一个编辑来修复语法错误,但是还有另一个错误:
ESI
在循环中保存一个指针,因此
JNE@DivLoop
在将整个地址空间转到
ESI=(int*)4
之前不会退出循环。也许您打算使用
dec ecx
,或
cmp
?FWIW,@PeterCordes:在我的汇编程序中,允许使用
DIV EAX、EBX
DIV EBX
。但是由于在一个版本中,
DIV EBX
生成了错误的代码,但是
DIV EAX,EBX
没有生成错误的代码,所以我总是使用后者。@PeterCordes:我没有逐字复制此代码(我的代码使用展开的循环,而且要复杂得多)。我想我忘了什么。我会修正的。啊,好吧,我想知道在一个基于工作代码的示例中,
diveax,ebx
是如何出现的!(是的,我可以说它一定不是逐字复制/粘贴的)。当你这样做的时候,我建议你发表一点评论,指出你不在循环内将EDX归零是故意的;上一个除法的余数是下一个肢体输入的上半部分。(这是故意的,对吧?这对BigInteger来说似乎是合理的)@PeterCordes:我想我在循环结束时的评论解释了这一点(即EDX没有归零)。