汇编程序如何处理在 2 个寄存器上分隔的值(例如 EDX:EAX)?
Posted
技术标签:
【中文标题】汇编程序如何处理在 2 个寄存器上分隔的值(例如 EDX:EAX)?【英文标题】:How do assemblers handle a value that is separated on 2 registers (e.g EDX:EAX)? 【发布时间】:2014-02-19 02:30:56 【问题描述】:我试图了解汇编程序如何处理这些。
目前我正在尝试通过手动编写汇编代码来学习汇编代码。但我想知道如何处理操作数“MUL”之后由 EDX:EAX 分隔的产品。
如果我现在想将该值除以另一个值,该怎么办,你如何在汇编中做到这一点?
【问题讨论】:
汇编器只是将人类阅读的指令转换为机器代码,它不“处理”任何东西。那是处理指令的 CPU 【参考方案1】:MUL 和 DIV 都被设计为使用 EDX:EAX 寄存器对 -- 隐式。
MUL 使用这些作为输出寄存器,DIV 使用这些作为输入寄存器。根据您的问题,您不必做任何事情 - 只需忽略其他寄存器,因为 DIV 实际上也会计算除法的余数,并将其放入 edx。
12313133*81231313 / 4342434 -->
mov eax, 12313133
mov ebx, 81231313
imul ebx ;; edx:eax = 38DAF:FE9E9FBD
mov ebx, 4342434
idiv ebx
mov [my_result], eax ;; = 230334407
mov [remainder], edx
请注意,如果商不适合 EAX,DIV 和 IDIV 将出错(#DE
异常)。使用不是从一个寄存器进行符号扩展或零扩展的被除数可以在INT_MIN / -1
或anything / 0
以外的情况下发生这种情况。
对于无符号的32位div r32
,如果EDX >= r32
会出错,否则不会。
如果您只使用带有一个 mul 和 div 的 x * a / b
,请确保 |a| < |b|
或您的输入 x
始终足够小。
【讨论】:
我没有意识到 DIV 使用 EDX:EAX 作为输入。这就是我在尝试跟踪 gdb 中的汇编代码时感到困惑的地方,我认为 DIV 只会使用 EAX 除以输入除数。谢谢!【参考方案2】:您可以使用结构来存储产品。这里我使用 32 位代码,将 1073741824 乘以 25,结果将超过 32 位寄存器可以容纳的结果,所以它会进入 edx:eax。
这是示例的 MASM 代码。
include masm32rt.inc
sProduct struct
LoDWord DD ?
HiDWord DD ?
sProduct ends
.data
fmtint db "%lld", 13, 10, 0
.data?
Product sProduct <?>
.code
start:
mov eax, 1073741824
mov ecx, 25
mul ecx
mov Product.HiDWord, edx
mov Product.LoDWord, eax
invoke crt_printf, offset fmtint, Product
inkey
invoke ExitProcess, 0
end start
并使用 calc 进行测试以确保结果正确。
【讨论】:
【参考方案3】:通常这意味着有一个双字乘法——8 字节的结果存储在 EDX:EAX 中——结果的高位 32 位存储在 EDX 中。
【讨论】:
以上是关于汇编程序如何处理在 2 个寄存器上分隔的值(例如 EDX:EAX)?的主要内容,如果未能解决你的问题,请参考以下文章