【发布时间】:2018-04-29 19:51:11
【问题描述】:
我的电话是add (%ecx,%esi,4),%edx。
我正在使用 gdb 查看代码并注意到如果使用 x/d 打印 ecx 中的值,它会打印 2(如果我使用 x/s 它会打印“/002”,如果这是相关的,则为 idk)。
那么寄存器esi持有0x2。
我认为 add 会像 edx = ecx + (esi * 4) 一样工作,应该是 0xA,但在这个 edx 之后是 0x6。
我查看了 add 语法,我相信我没有错,所以我想知道为什么它会显示为 0x6。
【问题讨论】:
-
内存中的值被添加到
edx。ecx和esi中的值仅与内存地址计算相关,即address = ecx + esi*4; edx += value_at(address);...gas 语法中的()表示内存访问(虽然不是在任何地方,mov 123,%eax也是地址 @ 的内存访问987654331@,常量需要$)。不要指望汇编语法具有“逻辑”意义,指令行为具有“逻辑”意义,就某些高级语言而言,指令是在 CPU 中 1:1 硬件实现的,因此它们遵循硬件设计逻辑和语法有时是“原样”。 -
只是不要猜测任何事情,始终为您感到困惑的任何事情找到适当的文档。如果你继续猜测,你会错 30% 次。
-
如果您想要
edx = ecx + (esi * 4),您可以使用lea (%ecx,%esi,4), %edx进行地址数学运算,然后将结果放入寄存器而不是从中加载。 Using LEA on values that aren't addresses / pointers? 我很惊讶add (%ecx,%esi,4),%edx这些输入没有出错;通常 0xA 不是有效地址。 (默认情况下,Linux 甚至不允许映射低 64kiB 的虚拟内存,因此 NULL 指针取消引用会出现段错误。)也许您正在调试内核/引导加载程序或使用 QEMU 的 gdb-stub 的东西?