【发布时间】:2018-12-22 07:01:10
【问题描述】:
我已经反汇编了一个使用 C scanf 函数的 x86 elf 二进制文件。
这是与scanf相关的反汇编代码块:
0x0804857a 89442404 mov dword [esp + 0x4], eax
0x0804857e c70424b28604. mov dword [esp], 0x80486b2
0x08048585 e8eafdffff call sym.imp.scanf
检查gdb,地址0x80486b2的内存包含数据0x7325(ASCII代码中的“%s”字符串)。
因此,这段代码显然所做的是推送 scanf 参数以相反的顺序在堆栈上,以便使用这两个参数调用scanf。
这通常在 C 中编码为 scanf ("%s", &somevar);
鉴于汇编代码,我在这里所期望的是 constant 0x80486b2 的 32 位表示被加载到地址中 em> 堆栈指针指向的 ...
相反,mov 指令已将 地址中的任何内容 0x80486b2 的 32 位表示加载到指向的地址中通过堆栈指针...对吗?
所以我们基本上得到的是mov 刚刚将数据从一个内存位置移动到另一个内存位置,根据这个x86 assembly introduction(其中过多的其他来源)是非法的(重点是我的):
在需要内存传输的情况下,源内存 内容必须首先加载到寄存器中,然后才能存储到 目标内存地址。
这里没有使用寄存器作为中介。
这怎么可能?
【问题讨论】:
-
仅在 AT&T 语法中,裸数被视为内存操作数(绝对地址)。您正在使用 Intel 语法,特别是来自
ndisasm的 NASM。 -
@petercordes 你能再扩展一下你的观点吗?我实际上使用了带有标志
architecture-flavor=Intel的gdb。一个简单的语法问题如何影响代码? -
我假设您已经习惯了 AT&T 语法,其中
0x80486b2是一个内存操作数,因此是这个问题。 (在 AT&T 中,$0x80486b2是立即数)。机器码是mov r/m32, imm32,但不同的语法以不同的方式表示该指令。 -
可能GDB让你认为实际的
"%s"被复制了,因为当你检查堆栈内容时,它会自动打印地址值+内容(为了程序员方便)?但是堆栈内存只包含那个值0x80486b2,字符串字节'%', 's', 0不驻留在esp指向的内存中,它们仍然在内存中的0x80486b2地址。
标签: assembly memory x86 stack mov