在装配中找出这种模式

时间:2014-07-28 11:49:49

标签: assembly

我在装配中一直看到以下模式,我想知道如何将其转换为伪代码,因为我不太清楚这里发生了什么。我把它的评论放在旁边,因为它怀疑发生了什么。

问题:

据推测,它们是一个函数的一部分,它有两个参数,即两个双精度数。然后它创建一个由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

3 个答案:

答案 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的指令