游戏辅助工具开发教程-从入门到精通之A2_1篇
作者:Figo
本篇起我们开始讲解汇编语言,最终目标是能读懂OllyDbg或IDA等反汇编工具得到的汇编代码,并可进行基本的高级语言嵌入汇编程序设计。我假设A1系列文章你已经读过,并掌握基本的高级语言程序设计方法。
对任何事物都要从ta产生的来龙去脉去研究,这样才能获得全面深刻的理解。话说上世纪40年代产生了第一代计算机,由于是基于二进制数制逻辑,人们可以和计算机交流的语言限于机器语言,你完全可以把它理解为某种外星语言:机器语言完全由0和1组成,当然,这属于人家计算机内部交流语言。我们都知道詹姆士.邦德代号007,知道周星星代号9527,知道圣诞节1225,情人节214…说这么多,其实是为了告诉大家:每个人的记忆力都很好的,相信我,汇编里面要你记住的常用代号不会比节日多:)。最初,为了要计算机按照人们意图行事,不得不通过机器语言与之交流,这就使得当时的程序员和远古时期的巫师一样稀少和神秘,因为机器语言容易出错,比如,你找出下面两个数字的不同:
1000110100011101001100011100011和1000110100011101001101011100011。
这还属于最简单的,如果是十几张纸都是0和1,让你找错,恐怕效率和正确率都不会太高。当人们意识到这个问题时,开始构造一种机制来简化编程,这样就有了汇编语言,它的思想就是互相替换:在人编写程序时候,用邦德替换007,周星星替换9527,…;在计算机执行时候,用007替换邦德,9527替换周星星,…。虽然这里说的是替换,但实际属于编译原理的东西,操作起来比较复杂,此处就不深入了。
永远记住,汇编语言是处理器相关的,此处主要以X86系列处理器为原型讲解,AMD公司的CPU一般都是兼容IA-32架构的,所以满足X86规则的汇编程序在AMD兼容芯片一样可以运行。
我们知道计算机几个主要配件:CPU、内存和硬盘等,而把这些配件整合到一起的就是主板,上面有各种形式的导线。下面是一张逻辑图:

上图中的I/O设备是指输入(Input)输出(Output)设备,如鼠标、键盘和摄像头等;I/O接口指的是USB、COM等接口;存储器主要指内存。从上图我们看到由CPU引出三种总线:控制、地址和数据总线,这是CPU坐阵指挥的途径,也就是说所有CPU指令最终都要表现在总线的操作上,而汇编语言本质上就是学会通过CPU操作总线的方法。那么,好奇的你就没有什么想问的吗?记住,有时候,好奇是比知识更重要的想象力!虽然好奇害死加菲猫。那么,CPU里面是怎么个组成呢?在我们学校有这么一个传说:胡伟武同学本科毕业设计就是用单片机搭出一个类8086芯片系统,这从一个侧面表达出X86的复杂。幸运的是,大家暂时不必了解太多;不幸的是,如果你打算像我的那个去360的师兄一样坚持走底层技术路线的话,你还是有必要读读Intel指令手册的。不过,我们暂时只需做个“幸运儿”:)。
当我们要求计算机对两个数执行求和运算时,CPU处理的流程是怎样的呢?假设要对a与b求和,a、b均已经存在于内存了。结合上面架构图来看:CPU通过控制总线发出读数据的指令,通过地址总线指明要读数据在内存中的地址,通过数据总线把数据传给CPU,CPU把数据存储在自己的寄存器中,然后通过算术逻辑部件(ALU)完成运算。这里多了两个名词:寄存器和算术逻辑部件,我将逐一讲解。
任何事物不能凭空存在,包括数据,CPU要交互的数据大部分放在内存和硬盘:硬盘向内存传输数据的速率远低于内存向CPU传输数据的速率;内存向CPU传输数据的速率远低于CPU的处理速率,现在的CPU为了缓解这个矛盾,一般都使用高速缓存机制,因为高速缓存向CPU传输数据的速率更快。那么,问题来了:CPU接收数据后把数据存放在哪里呢?答案是寄存器,寄存器的存取速率比内存快很多,主要用来存放运算过程中的数据地址、数据及中间结果等。本篇教程是以32位处理器为原型讲解,首先要讲的是最常用的通用寄存器:EAX、EBX、ECX和EDX。这就是寄存器代号,类似9527代表周星星:

有的同学看到上面的图可能像魔兽争霸一样:混乱之至了,怎么又有AH、AL和AX,这是什么啊?我们来论资排辈一下,《天龙八部》里面少林觉字辈高于玄字辈,因为他们老师的辈分不同所导致;那么把从AL到EAX按照位数排下辈:(AL、AH[8位])<AX[16位]<EAX[32位]。其实它们指的是同一个东西的不同部分,好比一个手由5个指头组成,一个人有2个手:但自始自终都是指的一个人,只是范围不同而已。同理EBX、ECX和EDX与EAX结构和命名类似,比如EBX也有BX、BH和BL。这样做的目的是提供最大的灵活性,比如有时你只需要存一个8位的值,那么就没必要占用全部寄存器,只需要用一部分即可:这与宿舍类似,一个宿舍假设可以容纳4个人,那么只有一个学生的时候占一张床即可,不必全部占满。
除了通用寄存器,还有变址和指针寄存器(EDI/ESI/ESP/EBP)、指令指针寄存器(EIP)、标志寄存器(EFlags):这些都是32位的寄存器。CPU中16位的寄存器是段寄存器,也就是说段寄存器这个房子的平米数比前面的寄存器要少,最大可以存16bit。

各种寄存器的主要用途如下表:
| 寄存器 | 代号 | 主要用途 |
| 累加器 | EAX | 算术运算、存储中间结果、函数返回值 |
| 基地址寄存器 | EBX | 基地址指针 |
| 计数器 | ECX | 循环计数、移位操作计数、重复操作计数 |
| 数据寄存器 | EDX | 乘除运算、存储中间结果 |
| 源变址寄存器 | ESI | 存储指针、串指令的源操作数指针 |
| 源目标变址寄存器 | EDI | 存储指针、串指令的目的操作数指针 |
| 基地址指针 | EBP | 存储指针、存取堆栈指针 |
| 栈顶指针 | ESP | 堆栈的栈顶指针 |
这节暂时讲到这里。
这种精简教程对偶们曾经学过汇编,但又没掌握的盆友们帮助很大。