有人可以将此程序集转换为C.

时间:2014-10-29 06:13:21

标签: c if-statement assembly x86 reverse-engineering

我有这个课程作业,我似乎无法弄明白。 重点是将此程序集转换为C(使用GNU汇编程序AT& T语法汇编的代码):

 .section .rdata,"dr"
LC0:
.ascii "%d\12\0"
.text
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movl %eax, (%esp)
call _atoi
movl %eax, 24(%esp)
cmpl $4, 24(%esp)
je L2
cmpl $6, 24(%esp)
jle L3
cmpl $9, 24(%esp)
jg L3
L2:
movl 24(%esp), %eax
addl $20, %eax
movl %eax, 28(%esp)
jmp L4
L3:
cmpl $0, 24(%esp)
jne L5
movl $44, 28(%esp)
jmp L4
L5:
cmpl $-1, 24(%esp)
jne L6
movl $-44, 28(%esp)
jmp L4
L6:
movl $99, 28(%esp)
L4:
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
然而,我总是迷失在L2上。似乎无论我们是否进入第一个if语句,我们总是会执行标签L2,这没有任何意义。我试图理解这一切,我得到的最接近的是这个C代码:

#include <stdio.h>

int main(int argc, char *argv[]){
    int y = 0;
    int x = atoi(*++argv);
    if (x != 4){
        if (x > 6 && x <= 9){
            y = 20 + x;
        }
        else if (x == 0){
            y = 44;
        }
        else if (x == -1){
            y = -44;
        }
        else {
            y = 99;
        }

    }
    else{
        y = 20 + x;
    }
    printf("%d %d", y, x);
}

有人可以帮忙解决我遇到的这个令人困惑的问题, 感谢

1 个答案:

答案 0 :(得分:4)

在解码编译器输出时,它通常有助于以更密集但仍然非常低级的形式(伪代码)重写汇编代码,仅使用基本的低级转换。关键是以一种难以出错的方式对少量指令进行分组/组合,但这更好地暴露了代码片段的内部逻辑。下一步是消除冗余存储和临时存储(如用于存储x + 20到y的EAX)。我正在跳过这里的第一步,但在更复杂的代码中执行此操作会很危险。

条件序列变为:

x equ [esp + 24]
y equ [esp + 28]

     if (x == 4) goto L2;
     if (x <= 6) goto L3;
     if (x >  9) goto L3;

L2:  y = x + 20; goto L4;

L3:  if (x != 0) goto L5;

     y = 44; goto L4;

L5:  if (x != -1) goto L6;

     y = -44; goto L4;

L6:  y = 99;

L4:  printf("%d\f", y);

前三个条件形成了编制者用来评估复杂条件的显着模式。编译器将该条件的第二项和第三项反转为使用其“跳转”解决方案片段;再次反转允许你编码原始条件(跳转到L2 /'然后'是OR,跳转到L3 /'其他'是AND NOTs):

if (x == 4 || !(x <= 6) && !(x > 9))

- &GT;

if (x == 4 || (x > 6) && (x <= 9))
鲍勃是你的叔叔。其他条件可能是链接if或switch语句的结果,很难说。但这几乎不重要。因此你的反编译已经几乎完美,你只是错过了一个小小的节拍。在中间步骤中,C-ified条件看起来像这样:

if (x == 4 || x > 6 && x <= 9)
{
   y = x + 20;
}
else // L3
{
   if (x == 0)
   {
      y = 44;
   }
   else // L5
   {
      if (x == -1)
      {
         y = -44;
      }
      else // L6
      {
         y = 99;
      }
   }
}

然后可以收紧:

if (x == 4 || x > 6 && x <= 9)
{
   y = x + 20;
}
else if (x == 0)
{
   y = 44;
}
else if (x == -1)
{
   y = -44;
}
else
{
   y = 99;
}

P.S。:(argv + 1)的值不会存储回argv,只是取消引用。因此它是atoi(*(argv + 1))atoi(argv[1])