汇编到 C 代码跳转

Posted

技术标签:

【中文标题】汇编到 C 代码跳转【英文标题】:Assembly to C Code jumps 【发布时间】:2015-04-08 08:45:23 【问题描述】:

我对此很陌生,但我正在尝试对汇编代码进行逆向工程,以弄清楚它在 C 中的作用。我正在查看的函数称为不同的函数 (func4),我将其分解为查看。对于我是否朝着正确的方向前进,我将不胜感激任何帮助或建议。

在原始函数中,0xe 在 %edx 中,0 在 %esi 中,而我试图发现的一个值(我们称之为 x)在 %edi 中。

func4

  0x00000000004010ff <+0>:  push   %rbx
  0x0000000000401100 <+1>:  mov    %edx,%eax 

所以现在 %eax 有 0xe。

  0x0000000000401102 <+3>:  sub    %esi,%eax

%eax = 0xe - 0

  0x0000000000401104 <+5>:  mov    %eax,%ebx    
  0x0000000000401106 <+7>:  shr    $0x1f,%ebx   

%ebx = %ebx >> 0x1f = 0

  0x0000000000401109 <+10>: add    %ebx,%eax    

%eax = %eax + %ebx = 0xe

  0x000000000040110b <+12>: sar    %eax     

我相信这是 sar %eax,1 的简写,应该是 7。

  0x000000000040110d <+14>: lea    (%rax,%rsi,1),%ebx   

现在,我认为 (%rax,%rsi,1) 表示 %rax + %rsi*1,即 7

  0x0000000000401110 <+17>: cmp    %edi,%ebx
  0x0000000000401112 <+19>: jle    0x401120 <func4+33>

这意味着如果 ebx

  0x0000000000401114 <+21>: lea    -0x1(%rbx),%edx      
  0x0000000000401117 <+24>: callq  0x4010ff <func4>

这就是我感到困惑的地方。我要再次使用该功能吗?只是寄存器中的值不同?

  0x000000000040111c <+29>: add    %eax,%ebx
  0x000000000040111e <+31>: jmp    0x40112e <func4+47>
  0x0000000000401120 <+33>: cmp    %edi,%ebx    
  0x0000000000401122 <+35>: jge    0x40112e <func4+47>
  0x0000000000401124 <+37>: lea    0x1(%rbx),%esi       
  0x0000000000401127 <+40>: callq  0x4010ff <func4>
  0x000000000040112c <+45>: add    %eax,%ebx
  0x000000000040112e <+47>: mov    %ebx,%eax    
  0x0000000000401130 <+49>: pop    %rbx
  0x0000000000401131 <+50>: retq 

【问题讨论】:

你能用英特尔语法发布这个东西吗?是的,它是递归的 您是否已经检查过程序中是否存在重定位? “callq”处的重定位将意味着调用另一个函数! 我认为它是完全用汇编编写的递归函数,因此它使用符合他的规则的寄存器。你能发布你的程序的反汇编吗? 谁能告诉我这个“方言”?他的第二条指令'mov %edx,%eax',当我使用我的VC2008反汇编时,意味着将eax移动到edx,但这里似乎意味着将edx移动到eax,即操作数被反转??? @PaulOgilvie 我认为你用 intel 语法和他在 AT&T 语法中的源代码进行反汇编。 【参考方案1】:

不要试图立即评估 func4。首先通过逐行翻译每一行汇编将其翻译成C。结果应如下所示:

int func4 (int edi, int esi, int edx)

    // temporaries
    int eax, ebx;

    eax = edx;
    eax = eax - esi;
    ebx = eax;
    ebx = (unsigned int)ebx >> 31;
    eax = eax + ebx;
    eax = eax >> 1;
    ebx = eax + esi + 1;
    if (ebx <= edi) goto L1;
    edx = ebx - 1;
    eax = func4 (edi, esi, edx);
    ebx = ebx + eax;
    goto L2;
L1:
    if (ebx >= edi) goto L2;
    esi = ebx + 1;
    eax = func4 (edi, esi, edx);
    ebx = ebx + eax;
L2:
    eax = ebx;
    return eax;

虽然很丑,但是很管用。

现在,据我了解,给定一个 y,您正在寻找一个 x 使得 y = func4 (x, 0, 14);

你有两个选择:

    重写 func4 使其变得足够容易理解,以便您弄清楚它的作用并猜测您必须通过哪个 x 才能获得给定的 y。 计算所有 x 值的 y = func4 (x, 0, 14),直到得到所需的 y

【讨论】:

请注意 sar %eaxeax = eax/2 不同,当 eax 为负时,移位将向下舍入(向 -infinity),而除数将向 0 舍入。实际上使用 ebx 的整个“移位 31”的东西是编译器对这种差异的修正,所以这 4 条指令应该只替换为 eax = eax/2

以上是关于汇编到 C 代码跳转的主要内容,如果未能解决你的问题,请参考以下文章

这个汇编代码是啥意思? [复制]

arm汇编b指令是绝对地址还是相对地址跳转?

嵌入式高手进 考试题解答

汇编语言中的函数调用

uboot启动第一阶段详解——汇编代码部分start.S

实现永远等待的汇编代码