mov 指令在 x86 汇编中将数据从内存获取到内存

mov instruction fetches data from memory to memory in x86 assembly

我反汇编了一个 x86 elf 二进制文件,它使用了 C scanf 函数。
这是与 scanf 相关的反汇编代码块:

0x0804857a      89442404       mov dword [esp + 0x4], eax  
0x0804857e      c70424b28604.  mov dword [esp], 0x80486b2                                 
0x08048585      e8eafdffff     call sym.imp.scanf  

检查gdb,地址0x80486b2处的内存包含数据0x7325([=%s"字符串35=]ASCII码).
所以这段代码显然做的是 pushing scanf 参数在堆栈上以相反的顺序调用 scanf 这两个参数。
这通常在 C 中编码为 scanf ("%s", &somevar);

根据汇编代码,我在这里所期望的是 常量 0x80486b232 位表示被加载到堆栈指针指向的地址中...
相反,mov 指令加载了 32 位表示的 地址处的任何内容 0x80486b2 进入堆栈指针指向的地址……对吗?

所以我们基本上得到的是 mov 刚刚将数据从 内存位置 移动到另一个 内存位置 ,根据这个x86 assembly introduction(在众多其他来源中)是非法的(重点是我的):

In cases where memory transfers are desired, the source memory contents must first be loaded into a register, then can be stored to the destination memory address.

这里没有使用寄存器作为中介。
这怎么可能?

指令mov dword [esp], 0x80486b2将32位立即数0x80486b2移动到ESP指向的32位内存位置。如果它将存储地址 0x80486b2 处的 32 位值移动到目标中,那么它将被写为 mov dword [esp], dword [0x80486b2]。但是,这不是 MOV 指令允许的操作数组合。

请注意,您的反汇编使用的是 NASM 语法。

If I understand well, the mov instruction here loaded the 32-bit representation of whatever was at the address 0x80486b2 into the address pointed to by the stack pointer ... Is that right ?

没有。指令

mov dword [esp], 0x80486b2

将立即数0x80486B2复制到寄存器ESP指向的地址。这个地方是传递给scanf函数的第一个参数。

So what we basically get is that mov has just moved around data from a memory location to another memory location, [...]

没有。该指令将立即数 32 位值移动到内存位置。本例中 MOV 的指令签名为:

MOV r/m32, imm32        Move imm32 to r/m32.

0x80486b2写入寄存器ESP指向的DWORD内存地址。

指令mov dword [esp + 0x4], eax确实将第二个参数从EAX传递给scanf