本附录主要针对于没有80X86汇编语言基础的读者。如果这部分读者通过本小节的阅读与学习,可以建立起对80x86汇编语言的基本认知。如果各位读者想要深入了解80x86汇编语言,建议阅读专业的汇编书籍。
寄存器
寄存器是80x86平台下汇编语言的基本组成之一,是一种非常快速的存储器,通常用来保存量小且对速度有苛刻要求的数据。
什么是寄存器
寄存器是一个统称,但是一般情况 下指的都是某一个寄存器,例如eax寄存器。但是eax寄存器又代表什么呢?可以说它本身什么也不代表,但是你可以赋予它代表任何事物的能力。其实这里我们所说的eax只不过是人们给它起的一个别名,就像是高级语言中的变量名一样, 实质上它只是代表一段寄存器上一段4字节的固定区域,而eax其实就是这段固定区域起始地址的别名而已。
寄存器用来做什么
我们可以将寄存器看作是CPU提供给我们的变量名,可以用其保存任何我们想保存的数据,只不过它的数量很少且使用时有很多的规定而已。
汇编语言中都有哪些寄存器
其实这个标题是错误的, 正确的问法应该是“80x86平台下的汇编语言都有哪些寄存我们知道汇编语言是有很多种的,不同平台下的汇编语言都是不一样的。
就80x86平台来说,其常用的寄存器共有28个,这28个寄存器的分布如图A-1所示。
这些寄存器都是做什么用的
虽然从理论上来讲80x86的寄存器是可以随便使用的,但是Intel公司还是对其做了一个约定。在绝大多情况下程序员与编译器都会遵从这个约定,因此少数不遵从约定的程序按照其“违约”程度的不同从而对其稳定性的影响也不尽相同。
以下就是通常情况下各个通用寄存器的用途。
- eax: 扩展累加寄存器(在乘/除法中被主动调用),多数情况下可以用于其他用途。
- ecx: 循环计数器,多数情况下可以用于其他用途。
- edx:数据寄存器, 常用来存放8字长数据的高32位,多数情况下可以用于其他用途。
- ebx:基址寄存器,常用作存放存储器地址,多数情况下可以用于其他用途。
- esp: 指向堆栈(最上面一个栈帧的栈顶),绝大多数情况下不可以用于他用。
- ebp: 指向最上面一个栈帧的栈顶的底部,一般情况下不可以用于他用。
- esi: 扩展目的指针(由高速内存数据传送指令使用),多数情况下可以用于其他用途。
- edi: 同上。
- eip: 指令指针(存放下一条要执行的指令的地址),几乎不可以用于他用。
寻址模式
寻址模式(Addressingmode)是为了访问指令操作数而设置的特定于某种硬件的机制,80x86提供了3种不同的操作数,即寄存器操作数、立即操作数与内存操作数。表A-1描述了这些操作数所对应的寻址方式。
数据传输指令
数据传输指令是指将一段数据从一个地方传递到另一个地方,但是在80x86汇编中究竟可以怎样传递数据呢?以最常用的mov指令为例,图A-2很好地解答了这一问题。
1.mov指令
mov指令用于将数据从一个地方传递到另一个地方,且两个操作数中必须有一个是寄存器。
- 操作数个数:2。
- 指令原型:mov目标操作数,源操作数。
- 执行操作:目标操作数等于源操作数。
此指令在使用时有以下几点需要注意:
- 目的数可以是通用寄存器、存储单元和段寄存器(CS段寄存器除外)。
- 立即数不能直接送段寄存器。
- 不允许再两个存储单元之间传送数据。
- 不允许再两个段寄存器之间传送信息。
2.push入栈指令
push人栈指令用于将指定的数据压人堆栈,数据人栈时高位字节先人栈,低位字节后入栈。
- 操作数个数: 1。
- 指令原型: push源操作数。
- 执行操作:将源操作数压人堆栈。
3. pop出栈指令
pop出栈指令用于将位于栈顶的数据弹出栈,数据弹出时低位字节先出栈,高位字节后出栈。
- 操作数个数: 1。
- 指令原型: pop 目标操作数。
- 执行操作:将栈顶的数据弹出,并保存在目标操作数中。
4. xchg交换指令
xchg是两个寄存器、寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同。
- 操作数个数: 2。
- 指令原型: xchg 目标操作数,源操作数。
- 执行操作:将目标操作数与源操作数的内容相交换。
5. lea有效地址传送指令
lea是微机8086 1 8088系列的一条指令, 取自英语Load effect address。此指令的作用是计算源操作数的有效地址,并将它存储到目标操作数中。源操作数是使用处理器寻址模式之一指定的内存地址(偏移量部分);目标操作数是通用寄存器。
- 操作数个数:2。
- 指令原型:lea寄存器,源操作数。
- 执行操作:将源操作数的地址传送到目标操作数的寄存器中。
6.pushf标志进栈指令
将堆栈指针递减2,并将EFLAGS寄存器的低16位(即FlAGS寄存器)压人堆栈,将整个EFLAGS寄存器复制到堆栈时,不会复制VM与RF标志(位16与17)。
- 操作数个数: 0。
- 指令原型: pushf。
- 执行操作:将标志寄存器的内容压人栈。
7.pope标志出栈指令
将栈顶的16位数据弹出, 并将它存储到EFLAGS寄存器的低16位(即FLAGS寄存此指令执行pushf指令的逆操作。
- 操作数个数: 0。
- 指令原型: popf。
- 执行操作:将栈顶的内容弹出到标志寄存器中。
算术运算与逻辑运算指令
算术运算与逻辑运算指令负责执行数学运算与逻辑运算功能, 执行此类指令除了能得到相应的结果外,部分指令还会改变标志位,从而对控制转移类指令的执行产生影响,进而控制程序流程与逻辑。
1. add加法指令
将目标操作数与源操作数相加,结果存储到目标操作数。目标操作数可以是寄存器或内存位置,源操作数可以是立即数、寄存器或内存位置(但不能在一条指令中使用两个内存操作数)。
- 操作数个数: 2。
- 指令原型: add 目标操作数,源操作数。
- 执行操作:将源操作数与目标操作数相加,并将结果保存在目标操作数中。
2. adc带进位的加法指令
将目标操作数、源操作数以及进位(CF)标志相加,结果存储到目标操作数。目标操作数可以是寄存器或内存位置,源操作数可以是立即数、寄存器或内存位置(但不能在一-条指令中使用两个内存操作数)。
- 操作数个数: 2。
- 指令原型:adc目标操作数,源操作数。
- 执行操作:将源操作数、目标操作数以及进位(CF)标志相加,并将结果保存在目标操作数中。
3. inc加1指令
将目标操作数加1,同时保持CF标志的状态不变。目标操作数可以是寄存器或内存位置。
- 操作数个数: 1。
- 指令原型: inc 目标操作数。
- 执行操作:将目标操作数加1,同时保持CF标志的状态不变。
4. sub减法指令
将目标操作数减去源操作数,结果存储到目标操作数。目标操作数可以是寄存器或内存位置,源操作数可以是立即数、寄存器或内存位置(但不能在一条指令中使用两个内存操作数)。
- 操作数个数:2。
- 指令原型:sub目标操作数,源操作数。
- 执行操作:将目标操作数与源操作数相减,将结果保存到目标操作数。
5.sbb带借位的减法指令
将源操作数与进位(CF)标志相加,然后从目标操作数减去此结果。减法的结果存储到目标操作数。目标操作数可以是寄存器或内存位置,源操作数可以是立即数、寄存器或内存位置(不过,不能在一条指令中使用两个内存操作数)。
- 操作数个数:2
- 指令原型:sbb目标操作数,源操作数。
- 执行操作:将源操作数与进位(CF)标志相加,然后从目标操作数减去此结果,将最终结果保存到目标操作数。
6. dec减1指令
将目标操作数减1,同时保持CF标志的状态不变,目标操作数可以是寄存器或内存位置。口操作数个数: 1。
- 指令原型: dec 目标操作数。
- 执行操作:将目标操作数减1,同时保持CF标志的状态不变。
7. mul无符号乘法指令
对目标操作数与源操作数执行无符号乘法,结果存储到目标操作数。目标操作数是位于AL、AX或EAX寄存器(取决于操作数的大小)中的隐式操作数,源操作数位于通用寄存器或内存位置。
- 操作数个数: 2。
- 指令原型: mul源操作数。
- 执行操作:将目标操作数与源操作数执行无符号乘法,结果存储到目标操作数。目标操作数是位于al、ax或eax寄存器(取决于操作数的大小)中的隐式操作数,源操作数位于通用寄存器或内存位置。
8. imul有符号的乘法指令
对两个有符号操作数执行乘法。口操作数个数:1~3。
- 指令原型: imul 目标操作数。
- 执行操作:对两个有符号操作数执行乘法。根据操作数的数量,此指令有3种形式。
- 单操作数形式。此形式与mul指令使用的形式完全相同, 源操作数(位于通用寄存器或内存位置)乘以al、ax或eax寄存器(取决于操作数大小)中的值,乘积分别存储到ax、dx:ax 或edx:eax寄存器。
- 双操作数形式。此种形式是目标操作数乘以源操作数,目标操作数是通用寄存器,源操作数可以是立即数、通用寄存器或内存位置,乘积存储到目标操作数位置。
- 三操作数形式。此种形式需要一个目标操作数与两个源操作数,第一一个源操作数(可以是通用寄存器或内存位置)乘以第二个源操作数(立即数),乘积存储到目标操作数(通用寄存器)。
9. div无符号除法指令
将ax寄存器、dx:ax寄存器对或edx:eax寄存器对中的值(被除数)除以(无符号)源操作数(除数), 结果存储到ax(ah:al)、dx:ax 或edx:eax寄存器,源操作数可以是通用寄存器或内存位置。
- 操作数个数: 2。
- 指令原型: div源操作数。
- 执行操作:将ax、dx:ax或edx:eax中的值(被除数)除以(无符号)源操作数(除数),结果存储到ax(ah:al)、dx:ax 或edx:eax寄存器。
10.idiv有符号除法指令
将al、ax或eax寄存器中的值除以(有符号)源操作数,结果存储到ax、dx:ax 或edx:eax寄存器。源操作数可以是通用寄存器或内存位置。
- 操作数个数: 2。
- 指令原型: idiv 源操作数。
- 执行操作:将al、ax或eax寄存器中的值除以(有符号)源操作数,结果存储到ax、dx:ax或edx:eax寄存器。
11. cmp比较指令
比较第一一个源操作数与第二个源操作数,并根据结果设置EFLAGS寄存器中的状态标志。比较操作通过将第一个源操作数减去第二个源操作数来实现,然后按照与SUB指令相同的方式设置状态标志。将立即数用作操作数时,会按照符号扩展方式将它扩展到第一个源操作数的长度。
- 操作数个数: 2。
- 指令原型: cmp源操作数,源操作数。
- 执行操作:比较第一个源操作数与第二个源操作数,并根据结果设置EFLAGS寄存器中的状态标志。
12. and逻辑与指令
在目标(第一个)与源(第二个)操作数上执行位“与”运算,结果存储到目标操作数位置。源操作数可以是立即数、寄存器或内存位置,目标操作数可以是寄存器或内存位置。
- 操作数个数: 2。
- 指令原型:and目标操作数,源操作数。
- 执行操作:将目标操作数与源操作数进行逐位“与”运算,结果存储到目标操作数位置。
13. or逻辑或指令
在目标操作数与源操作数之间执行逐位“或”操作,结果存储到目标操作数位置。源操作数可以是立即数、寄存器或内存位置;目标操作数可以是寄存器或内存位置(但不能在一一条指令中使用两个内存操作数)。
- 操作数个数: 2。
- 指令原型: or目标操作数,源操作数。
- 执行操作:将目标操作数与源操作数进行逐位“或”操作,结果存储到目标操作数位置。
14. xor逻辑异或指令
对目标操作数与源操作数执行逐位“异或”运算,结果存储到目标操作数位置。源操作数可以是立即数、寄存器或内存位置,目标操作数可以是寄存器或内存位置(但不能在一条指令中使用两个内存操作数)。
- 操作数个数: 2。
- 指令原型:xor目标操作数,源操作数。
- 执行操作:将目标操作数与源操作数进行逐位“异或”(xor) 操作,结果存储到目标操作数位置。
15. not逻辑非指令
对目标操作数执行逐位“非”操作(将1改为0,将0改为1),结果存储到目标操作数位置, 目标操作数可以是寄存器或内存位置。
- 操作数个数: 1。
- 指令原型: not目标操作数。
- 执行操作:对目标操作数执行逐位“非”操作(每个1设置为0,每个0设置为1),结果存储到目标操作数位置。
16. test逻辑比较指令
将第一个源操作数与第二个源操作数的逐位逻辑“与”,根据结果设置SF、ZF及PF状态标志,然后丢弃结果。
- 操作数个数: 2。
- 指令原型: test 源操作数,源操作数。
- 执行操作:第一个源操作数与第二个源操作数进行逐位逻辑“与”,并根据结果设置SF、ZF及PF状态标志,然后丢弃结果。
串操作指令
串操作指令用于操作某一内存区域中相同连续类型数据构成的一个整体(相当于一个数组),这种结构一般被用于保存字符串或其他连续存放的单一类型数据。
movs串传送指令
将源操作数指定的字节、字或双字移到目标操作数指定的位置。源操作数与目标操作数都是内存位置。源操作数的地址从ds:esi或ds:si寄存器中读取(具体取决于指令的地址大小属性,分别为32或16);目标操作数的地址从es:edi或es:di寄存器中读取(具体也取决于指令的地址大小属性)。
- 操作数个数:2
- 指令原型:movs目标操作数,源操作数。
stos存入串指令
将al、ax 或eax寄存器中的字节、字或双字分别存储到目标操作数。目标操作数是内存位置,其地址从es:edi或es:di寄存器读取(具体取决于指令的地址大小属性,分别是32或16)。
- 操作数个数: 1。
- 指令原型: stos目标操作数。
- 执行操作:将al、ax或eax寄存器中的字节、字或双字存储到目标操作数。
lods取出串指令
将源操作数中的字节、字或双字分别加载到al. ax或eax寄存器。源操作数是内存位置,其地址从ds:edi或ds:si寄存器中读取(具体取决于指令的地址大小属性)。
- 操作数个数: 1。
- 指令原型: lods 源操作数。
- 执行操作:将源操作数中的字节、字或双字分别加载到al、ax 或eax寄存器。
cmps串比较指令
比较第一个源操作数指定的字节、字或双字与第二个源操作数指定的字节、字或双字,并根据结果设置EFLAGS寄存器中的状态标志。两个源操作数都位于内存,第-一个源操作数的地址从ds:esi或ds:si寄存器中读取(具体取决于指令的地址大小属性),第二个源操作数的地址从es:edi或es:di寄存器中读取(具体也取决于指令的地址大小属性)。
- 操作数个数: 2。
- 指令原型:cmps源操作数,源操作数。
- 执行操作:比较第一个源操作数指定的字节、字或双字与第二个源操作数指定的字节、字或双字,并根据结果设置EFLAGS寄存器中的状态标志。
rep重复操作前缀
按计数寄存器(E) CX中指定的次数重复执行字符串指令,或重复到ZF标志不再满足指定的条件。
- 操作数个数: 0。口指令原型: rep。
- 执行操作:按计数寄存器(E) Cx中指定的次数重复执行字符串指令,或重复到ZF标志不再满足指定的条件为止。
控制转移指令
控制转移指令负责控制程序执行流程,它们一般会导致当前指令的执行轨迹发生改变,或执行调用子程序的功能。
jmp无条件转移指令
将程序控制权转移到指令流中的另一个点,不记录返回信息。口操作数个数: 1。
- 指令原型: jmp目标操作数。
- 执行操作:将程序控制权转移到指令流中的另一个点,不记录返回信息。目标操作数指定要跳转到的指令地址,此操作数可以是立即数、通用寄存器或内存位置。
jcc有条件转移指令
检查EFLAGS寄存器中一个或多个状态标志(CF、 OF、PF、SF及ZF)的状态,如果标志处于指定的状态(条件),则跳转到目标操作数指定的目标指令。
- 操作数个数: 1。
- 指令原型:jcc目标操作数。
- 执行操作:这代表的一一类指令的集合,jcc后面的cc可以替换成任何字符以使其组合成常见的跳转指令(如jne、je、jnc、jpe等)。此类指令根据判定条件的不同检查EFLAGS寄存器中一个或多个状态标志(CF、 OF、PF、SF及ZF)的状态,如果标志处于指定的状态(条件),则跳转到目标操作数指定的地址。
loop循环指令
将ecx或Cx寄存器用作计数器,执行循环操作。loop指令每执行一次,计数寄存器递减,然后检查是否为0。如果计数为0,则终止循环,并继续执行程序中loop指令后面的指令。如果计数器不为零,则执行近跳转,跳转到目标操作数,假定它是位于循环开头的指令。
- 操作数个数: 0。口指令原型: loop。
- 执行操作:将ecx或Cx寄存器用作计数器,执行循环操作。loop指令每执行一次, 计数寄存器递减,然后检查是否为0,如果计数为0,则终止循环,并继续执行程序中loop指令后面的指令。
call函数调用指令
将函数返回信息保存到堆栈上,并跳转到目标操作数指定的函数地址执行。目标操作数指定被调用过程中第.条指令的地址,此操作数可以是立即数、通用寄存器或内存位置。
- 操作数个数: 1。
- 指令原型:call目标操作数。
- 执行操作:将函数返回信息保存到堆栈上,并跳转到目标操作数指定的函数地址执行。
ret返回指令
将程序控制权转移到位于栈顶的返回地址。此地址通常由call 指令放人堆栈,返回目标是call指令的下一条指令。
- 操作数个数: 0。口指令原型: ret。
- 执行操作:将程序控制权转移到位于栈顶的返回地址。
处理器控制指令
处理器控制指令用于控制当前的处理器状态,这些指令可以控制处理器的暂停、等待、交权等各项工作。
clc 进位置0指令
- 操作数个数: 0。D指令原型: clc。
- 执行操作:清除EFLAGS寄存器中的CF标志。
cmc进位求反指令
- 操作数个数: 0。口指令原型: cmc。
- 执行操作:对EFLAGS寄存器中的CF标志求补。
stc进位置1指令
- 操作数个数: 0。口指令原型: stC。
- 执行操作: 设置EFLAGS寄存器中的CF标志。
nop无操作指令
不执行操作此指令是单字节指令,会占用指令流空间,但不会影响机器上下文(EIP寄存器除外)。
- 操作数个数: 0。口指令原型: nop。
- 执行操作:不执行任何操作。
hlt停机指令
停止指令执行,并使处理器进入“暂停”状态。启用的中断、NMI或复位都会恢复执行。口操作数个数: 0。
- 指令原型: hlt。
- 执行操作:停止指令执行,并使处理器进入“暂停”状态。
by Covteam-Sma11_Tim3
生活不易,多才多艺。