有人可以将此程序集转换为 C 语言吗

标签 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);
}

有人可以帮助解决我遇到的这个令人困惑的问题吗? 谢谢

最佳答案

在解码编译器输出时,它通常有助于仅使用基本的低级转换,以更密集但仍然非常低级的形式(伪代码)重写汇编代码。关键是以一种很难出错但能更好地暴露代码片段的内部逻辑的方式对少量指令进行分组/组合。下一步是消除冗余存储和临时数据(例如用于存储 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/'then' 是 OR,跳转到 L3/'else' 是 AND NOT):

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

->

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

鲍勃是你的叔叔。其他条件可能是链式 if 或 switch 语句的结果,很难说。但这并不重要。因此你的反编译已经几乎完美了,你只是错过了一点点。在中间步骤中,C 化条件语句如下所示:

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])

关于有人可以将此程序集转换为 C 语言吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26623801/

相关文章:

c - 使用环境变量执行不同的文件

c++ - Win32 -- 如何管理我的鼠标钩子(Hook)线程

c - 如何用 C 语言从 xml 文件中解析/提取一些信息

c - 在动态分配的结构中初始化动态分配的结构

javascript - javascript中if语句内的逗号

jQuery if/else 语句

javascript - 检查数组键是否等于某个值 JavaScript

linux - x86-64 AMD 上 CALL 指令的操作数生成

assembly - 这个 RSB 指令有什么作用?

c - 汇编程序的大小是否与 C 程序几乎相同