我在装配中一直看到以下模式,我想知道如何将其转换为伪代码,因为我不太清楚这里发生了什么。我把它的评论放在旁边,因为它怀疑发生了什么。
问题:
据推测,它们是一个函数的一部分,它有两个参数,即两个双精度数。然后它创建一个由2个数组组成的数组[2]并将这些双精度加载到数组中。那是怎么回事?
8049a73: ba 8d ae 04 08 mov $0x804ae8d,%edx // put two numbers into register edx, %d %d (found on gdb)
8049a78: 8b 45 08 mov 0x8(%ebp),%eax // take parameter 1 and put into register eax
8049a7b: 8d 4d f0 lea -0x10(%ebp),%ecx // take a local variable and put this into register ecx ???
8049a7e: 89 4c 24 0c mov %ecx,0xc(%esp) // move ecx onto the top of the stack ???
8049a82: 8d 4d f4 lea -0xc(%ebp),%ecx // move this other local variable and put this onto the top of the stack
8049a85: 89 4c 24 08 mov %ecx,0x8(%esp) // move this variable to the top of the stack too
8049a89: 89 54 24 04 mov %edx,0x4(%esp) // from the edx register, put that at the top of the stack too
8049a8d: 89 04 24 mov %eax,(%esp) // then compare what is at eax with the address of esp ???
8049a90: e8 db f1 ff ff call 8048c70 <sscanf@plt>
8049a95: 83 f8 02 cmp $0x2,%eax // compare value in the register eax against constant 2
答案 0 :(得分:3)
%d
表示整数,而不是双精度。阅读sscanf
的文档。
代码正在进行sscanf
调用,根据适用的调用约定(从(%esp)
开始的4个参数)在堆栈上设置参数,然后检查返回的值。
该函数在0x8(%ebp)
处有一个传入参数(我将称之为arg_08
),在-0x10(%ebp)
和-0xc(%ebp)
处有两个局部变量(我将称之为{{1}分别是}和local_10
。因此,等效的C代码是:
local_0c
答案 1 :(得分:1)
从你的上一个问题......
int *array[3]; // Moving from registers to %esp
int return_value = sscanf(param1, "%d %d %d", array[0], array[1], array[2]);
if(return_value == 3): // If there were 3 integers... see sscanf documentation
...
你可以通过一些线索找出很多东西。例如,我们现在知道函数原型看起来大致如下:
level_3(char* param1 ...);
因为我们知道sscanf的原型:
int sscanf ( const char * s, const char * format, ...);
另外,请记住%eax
寄存器保存被调用函数的返回值的规则,在本例中为sscanf,因此比较基本上是检查param1中是否有3个整数。此外,移动到%esp
的某个偏移量是为要调用的函数设置args; -%ebp
用于局部变量,+%ebp
用于函数自己的参数。
答案 2 :(得分:0)
它将函数参数放入堆栈以准备子程序调用
大多数x86-C-ABI(应用程序二进制接口,调用约定)要求将函数int foo(int arg1, float arg2, char *arg3)
等参数放在堆栈中,顺序相反:
push arg3
push arg2
push arg1
call foo
优化编译器可以改为编写
sub 12, %esp
mov arg3, 8(%esp)
mov arg2, 4(%esp)
mov arg1, (%esp)
call foo
这可能更快,因为%esp
没有被每条指令修改,因此在流水线机器上,不需要延迟操作数获取,以便下一条需要%esp
的指令