指针取消引用和乘法的基本 C/x86 汇编代码分步说明

Step-by-step explanation of basic C / x86 assembly code for pointer dereference and multiply

提问人:UnusualCommonSense 提问时间:9/15/2022 最后编辑:Peter CordesUnusualCommonSense 更新时间:9/16/2022 访问量:205

问:

我今天来到这里,因为我目前正在大学里做汇编 x86 的介绍工作。正如我们之前做 C 语言一样,我们的老师要求我们解释这部分代码。c code associated with the problem

我对它的作用的基本理解是:

  • EAX 将包含与 y 关联的内存区域的值。
  • ECX 将包含与 EAX 关联的内存区域的值,即 指向 y 的指针。
  • IMUL 将指针 EAX 的值(即指向 Y 的指针)和 X 的值相乘。
  • 我们在 EDX 中移动 y 的指针,然后将乘法的值移动到 y 的指针。

我说得对吗?如果没有,有人能给我一个更好的解释我误解的部分吗?

先谢谢你。

C 组件 x86

评论

2赞 500 - Internal Server Error 9/15/2022
如您所说,第一条指令将指针加载到 into 。其次,使用指针加载 into 的值。第三,将该值乘以 。第四,再次加载指针。第五,将乘法结果存储在 的地址中。yeaxyecxxyecxy
0赞 UnusualCommonSense 9/15/2022
谢谢,我想我在第 2 和第 5 条指令中弄错了。
4赞 Bodo 9/15/2022
提问时请不要上传代码/数据/错误的图片。
0赞 Peter Cordes 9/16/2022
这是低效的编译器输出;它可以保存在对面的寄存器中,这样它就可以存储回相同的地址。进入 EDX 的第二个负载是冗余的;它已经在 EAX 中拥有它。顺便说一句,我们可以从指令长度中看出,和 实际上是局部变量的别名,而不是全局符号(绝对地址)。一些反汇编器喜欢发明这样的名称,就像 MSVC 在生成 asm 输出时所做的那样。yimulyxy[ebp-4]
0赞 Peter Cordes 9/16/2022
godbolt.org/z/f8bGM4fdG 显示禁用优化的 GCC 使 asm 像这样,甚至对于 ,但不是 clang。但是,叮当声冗余加载两次,当然会禁用优化。即使启用了基本的优化,编译器当然也意识到他们只需要加载一次(godbolt.org/z/d45jYK98T - 为了避免整个函数优化,我不得不将本地变量的地址传递给另一个函数。我应该只使用全局变量,但 Godbolt 突出显示了哪些指令与哪个源代码行一起使用。*y *= x*y = *y * xy-O1y

答:

0赞 rcgldr 9/15/2022 #1

带注释的代码:

        mov     eax,dword ptr [y]         ;eax = y
        mov     ecx,dword ptr [eax]       ;ecx = *y
        imul    ecx,dword ptr [x]         ;ecx = (*y) * x
        mov     edx,dword ptr [y]         ;edx = y
        mov     dword ptr[edx], ecx       ;(*y) = (*y) * x
1赞 Lundin 9/15/2022 #2

与任何汇编程序一样,您几乎需要手头拿着 ISA 手册,因为每条指令都有很多不同之处,具体取决于您传递给它的内容。

首先查看“dword ptr”是什么意思?所以基本上这个 32 位访问某个地址的内容。

由于是指针,因此 的内容是可以找到的地址。因此,首先将地址移入,然后将刚刚上传到的地址的内容移入 .yy*yyeaxeaxecx

imul有两个操作数是这样的:

  • 双操作数形式。在这种形式下,目标操作数(第一个操作数)乘以源操作数(第二个操作数)。目标操作数是通用寄存器,源操作数是即时值、通用寄存器或内存位置。然后,产品将存储在目标操作数位置。

因此,它与存储在 的 中的任何内容相乘,即 的内容。并将结果存储在 中。ecxdword ptr[x]xecx

然后,该地址再次上传到寄存器(可能是优化缺陷,因为已经持有它)。然后将存储的乘法结果移动到该位置。yedxeaxexc

评论

0赞 rcgldr 9/16/2022
在这种情况下,是多余的,不需要,因为使用了寄存器(eax、ecx、edx)。通常只在立即移动时才需要使用,例如 .也许这是英特尔汇编程序特有的东西。Masm 不需要 或 括号在 或 上。dword ptrdword ptrmov dword ptr [eax],23dword ptrxy
0赞 Lundin 9/16/2022
@rcgldr我认为这段代码来自反汇编的 C,可能没有禁用优化。它总是比手写的汇编程序更奇怪。