汇编程序如何处理在 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 / -1anything / 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)?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理在应用程序有效期内结束自动续订的订阅

Node.js:如何处理在字典中查找同名的不同城市?

如何处理在运行时确定类型的数组的声明和分配?

我应该如何处理在我的 setup.py 脚本中导入第三方库?

如何处理在 php mysql 中返回多个值的内部查询?

在 Grafana 中,我们如何处理在图表/面板中返回 0 行的查询?