汇编与对应c伪码

对于《逆向工程实战》第一章~第二章学习过程中的一些汇编代码及对应的c代码的积累。

第一章、x86与x64

1、数据移动

(1)

(2)

(3)

(4)

2、控制流

1.if-else——包含一个其后紧跟Jcc系列指令的compare/test指令。

2.switch-case——一个if-else语句序列。

(1)

(2)

3.循环。

(1)

(2)lstrlenA是char环境的字符串函数.

(3)

第二章、ARM

1、数据加载与存储——LDR与STR

(1)假定R0中保存有指向一个KDPC结构的指针——

2、分支跳转与条件执行
  • 最常用的比较指令可能就是CMP。其语法为 CMP Rn,x,其中Rn是寄存器,x可以是立即寄存器或桶式移位操作。其语义与x86中的同名指令相同:执行Rn-x,设置相应的标志位后丢弃结果。通常这条指令后面会跟随一个条件分支跳转。下面是一个用法示例及其伪码——


  • 第二个常用的比较指令是TST,其语法与CMP相同。它的语义与x86中的TEST指令相同:执行Rn&x,设置相应的标志位,然后丢弃结果。通常tst指令用于测试两个值是否相等,或者用于测试标志位是否置起。与多数比较指令一样,使用这条指令时通常后面会跟随一个条件分支跳转指令。

  • Thumb-2状态下,有两个常用的比较指令:CBZ和CBNZ。它们的语法很简单:cBz/ CBNZ Rn label,其中Rn是寄存器,1abe1是如果条件为真时要跳转的目标分支偏移量。如果寄存器值为0,cBz就跳转到标签指定的分支。CBNz也是一样,除了它检查的条件为非0。这两个指令通常用于检查一个数是否为0,或者一个指针是否为NULL。下面是典型用法——

  • 在分支跳转指令(B)后添加后缀(BEQ、BE、BLT、BLs等)可以执行条件分支跳转。实际上,绝大多数ARM指令都可以通过这种方式条件执行。如果条件没有满足指令可以被看作是no-op。指令级的条件执行能够降低分支跳转数量,这可能意味着执行时间的缩短。下面是一个例子——

(1)Thumb状态——与多数ARM指令不同, Thumb指令不能在没有IT(if-then)的情况下条件执行(B指令例外)。IT指令是 Thumb-2专有的指令,支持其后最多4条指令可以条件执行。通用的语是:ITxyzcc,其中cc是第一条指令的条件编码,x、y和z分别是第二、三、四条指令的条件。第一条指令之后的条件用一个或两个字母表示:T或E。T是指条件必须匹配cc才能执行,E是指只有条件与cc相反才能执行。如下例所示——


(2)switch-case


其他

1.一个函数及对应汇编代码详解——函数如下——其中,以下代码是没有任何作用的,只是为了让我们在反汇编时好定位代码的位置。

_asm{
 mov edi,edi
 mov edi,edi
}

完整函数——

#include <stdio.h>
int main()
{
  int i;
  int result=0;
  _asm{
   mov edi,edi
   mov edi,edi
   }

  for (i=0;i<20;++i)
   result+=2;
  return result;
}

汇编及解释如下图——

2.正常情况下,开启了canary保护机制的程序的canary取值操作的汇编代码——
(1)32位:

mov     eax, large gs:14h
mov     [ebp+var_C], eax

(2)64位——

mov     rax, fs:28h        //fs为段寄存器
mov     [rbp+var_8], rax   //这两句表明程序编译时开启了canary保护,用于取canary值保存在[rbp-0x8h]处