首先,为了方便我们后面的逆向,我们选择一个简单的编译开发环境。

这里,我选择TC2.0

TC2.0是一个集成的开发环境,它集成了以下文件:

TC.EXE 集成编译器

EMU.LIB 8087仿真库 ,作用:系统将同8087仿真器连接,得到exe文件,只能用于程序的编译。

CS.LIB 不同模式运行库 ,作用:对于windows下程序的运行模式有很多种,普通用户模式、管理员模式,不同的运行模式,可能决定用户获得的不同的信息,该库决定了程序在不同模式下的运行机制。

C0S.OBJ 不同模式的共同启动代码

MATHS.LIB MATH(C、H、L、M、S).lib是编译器的五种存储模式,该maths.lib规定了tc2.0编译器的存储模式,连接成.exe的前提条件之一。

GRAPHICS.LIB C语言图形编程 图形库文件:

因为在编写C的图形程序时,用到了字体,文字库等库文件,生成的exe文件必须与这些库文件放在一起,程序才能正确跑起来,为了方便,我将这些文件都连接到了GRAPHICS.LIB这个文件中,以后编译好自己的程序后,只需一个exe文件就可以运行了,不需要别的什么文件了。

android 反汇编寄存器寄存器 反汇编lib_资源分配


**OK,我们最简易的集成环境搭建完成,接下来,我们将在这里写出.c,编译链接成.exe文件

**

在我们程序运行之前,系统大多会为我们程序将要使用的内存资源进行分配,然后运行我们的程序工作,结束后程序在对分配给我们的资源进行释放。

资源分配程序->我们写的程序->资源释放程序

TC2.0开发环境下资源分配程序与资源释放程序都C0S.OBJ中。

C0S.OBJ中代码结构类似:

start;
运行资源分配程序
调用main函数
运行资源释放程序
end;

于是,我们重写了C0S.OBJ。

android 反汇编寄存器寄存器 反汇编lib_main函数_02


红色部分是为我们.c程序申请栈空间与数据存储空间相当于资源分配程序

蓝色部分等价于main函数调用,调用的是s:这个地址后面储存的指令。相当于运行main函数

绿色部分为结束我们的程序进程,cpu的使用权交付给cpu,相当于资源释放程序好,我们写一个c程序编译连接必要的库和启动代码。

c程序如下:

android 反汇编寄存器寄存器 反汇编lib_操作系统_03


这里面我们没用main函数,因为我们自己重写了启动代码,所以有没有main函数已经无所谓了,我们这个代码链接的时候会自动的插入启动代码的S:后面。被当做main函数调用。

ds:0X100默认保存为数组的内存空间(这里搞了好久才发现,具体原因未知,留个疑问,待以后解决吧)

0xb800:0000为显存的地址,把字符放到这里会自动显示到显示屏上,单位2Byte,结构为(字符,属性),即低位存字符,高位存属性,0x2是字符的属性,绿色。

一个简单的输出KISS程序就写好了。

我们运行试一试:

android 反汇编寄存器寄存器 反汇编lib_android 反汇编寄存器寄存器_04


看,程序的第一行显示了绿色的KISS,成功。

于是,重点来了:(这里才是重点!!!)我们用windows自带的debug反汇编一下,得到如下汇编指令
我把这些指令全部翻译了一遍。

0B57:0000 B84F0B        MOV     AX,0B4F
0B57:0003 8ED0          MOV     SS,AX
0B57:0005 BC8000        MOV     SP,0080     
0B57:0008 E80500        CALL    0010                            ;调用jazzi函数
0B57:000B B8004C        MOV     AX,4C00
0B57:000E CD21          INT     21                              ;资源分配资源销毁 的启动程序
 
0B57:0010 55             PUSH    BP
0B57:0011 8BEC          MOV     BP,SP                           ;保存进入函数前的栈顶地址
 
0B57:0013 83EC02        SUB     SP,+02                          ;进入函数后,int i=0中的i内存保存在以原栈顶为栈底的栈中
0B57:0016 56                PUSH    SI                          ;si在子函数中值可能改变,所以原si值入栈
0B57:0017 33F6              XOR     SI,SI                       ;si=0 
0B57:0019 C746FE0000    MOV     WORD PTR [BP-02],0000           ;给i=0
0B57:001E 33F6              XOR     SI,SI                       ;si=0 
0B57:0020 EB32              JMP     0054
0B57:0022 8BDE              MOV     BX,SI                       ;等价于temp=i
0B57:0024 81C30001          ADD     BX,0100                     ;等价于temp=0x100+i
0B57:0028 8A07              MOV     AL,[BX]                     ;把ds:[0x100+i]中的值赋给AL,即‘K’'I''S''S'ascll码的十
                                                                ;六进制
0B57:002A 50                PUSH    AX                          ;+++++++++++++保存AX的值,因为以下代码要改变AX
0B57:002B 8BC6              MOV     AX,SI                       ;ax=i
0B57:002D D1E0              SHL     AX,1                        ;ax=2*i
0B57:002F 99                CWD                                 ;将ax变为双字节,高16位都为0
0B57:0030 050000            ADD     AX,0000                     ;ax=i*2+0
0B57:0033 81D200B8          ADC     DX,B800                     ;显存的段地址
0B57:0037 8BD8              MOV     BX,AX                       ;把ax的低16位赋给bx,即bx存着显存的最初偏移地址0000
0B57:0039 8EC2              MOV     ES,DX                       ;把显存的段地址赋给ES
0B57:003B 58                POP     AX                          ;+++++++++++++恢复AX的值
0B57:003C 26                ES:                                 ;改变[]的段地址罢了
0B57:003D 8807              MOV     [BX],AL                     ;因为显存中低位装着字符,所以把字符赋给这个显存地址
0B57:003F 8BC6              MOV     AX,SI                       ;-----------------------------------
0B57:0041 D1E0              SHL     AX,1                        ;与上面套路相同
0B57:0043 99                CWD
0B57:0044 050100            ADD     AX,0001
0B57:0047 81D200B8          ADC     DX,B800                     ;ax=i*2+1
0B57:004B 8BD8              MOV     BX,AX               
0B57:004D 8EC2              MOV     ES,DX                       ;------------------------------------
0B57:004F 26                ES:
0B57:0050 C60702            MOV     BYTE PTR [BX],02            ;只不过这里是吧02这个值赋给显存地址的高位,02表示绿色
0B57:0053 46                INC     SI                          ;等价于i++
0B57:0054 83FE04            CMP     SI,+04                      ;比较si是否为4,如果是4则退出
0B57:0057 7CC9              JL      0022                        ;如果si小于4,转移到22处
 
0B57:0059 5E                POP     SI                          ;原si值出栈,si恢复刚开始的值
0B57:005A 8BE5              MOV     SP,BP                       ;将子函数的栈中元素全部出栈,栈顶恢复为原栈顶的位置
0B57:005C 5D                POP     BP                          ;栈底恢复为原栈底的位置
0B57:005D C3                RET                                 ;程序交付启动函数处理后续