Assembly 添加(汇编)指令的工作方式与我认为的不一样

Assembly 添加(汇编)指令的工作方式与我认为的不一样,assembly,x86,Assembly,X86,我有行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。首先,您的程序集使用的是AT&T语法,这意味着指令如下所示: movl src,dest 给出的代码实际上与

我有行
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。

首先,您的程序集使用的是AT&T语法,这意味着指令如下所示:

movl src,dest
给出的代码实际上与此类似

然后寄存器esi保持0x2。我认为add的工作原理类似于edx=ecx+(esi*4),它应该是0xA,但在此之后,edx保持0x6


它实际上是这样工作的:将
edx的值添加到地址处的值(ecx+esi*4)

内存中的值添加到
edx
ecx
esi
中的值仅与内存地址计算相关,即
address=ecx+esi*4;edx+=地址处的值。。。gas语法中的
()
表示内存访问(虽然不是到处都是,
mov 123,%eax
也是地址
123
的内存访问,因为它需要
$
常量)。不要期望汇编语法具有“逻辑”意义,指令行为具有“逻辑”意义,对于某些高级语言来说,指令是在CPU中实现的1:1硬件,因此它们遵循硬件设计逻辑,语法有时是“按原样”的。只是不要猜测任何事,无论什么让你感到困惑,都要找到合适的文档。如果你继续猜测,你可能会错30%。如果你想要
edx=ecx+(esi*4)
,你可以使用
lea(%ecx,%esi,4),%edx
进行地址计算,然后将结果放入寄存器,而不是从寄存器加载。我很惊讶
add(%ecx,%esi,4),%edx
没有对这些输入出错;通常0xA不是有效地址。(默认情况下,Linux甚至不允许映射低64kiB的虚拟内存,因此空指针取消引用将导致错误。)也许您正在调试内核/引导加载程序或QEMU的gdb存根?