Intel x86微处理器的组成结构
汇编语言源程序的结构
简化段定义的程序结构
内存模型
在实际函数调用的过程中,函数的参数是从右向左依次压入栈中的。
内部寄存器
通用寄存器
功能:主要用于算术计算和数据传送。
AX,BX,CX,DX寄存器可以作为两个单独的8位使用。但SI,DI,BP,SP不可分开使用。
汇编语言的基本元素
定义数据
BYTE 8bit无符号整数,关键词DB。
WORD 16bit无符号整数,关键词DW。WORD中的数据采用小端存储的方式。
符号常量,不占用任何实际的存储空间。只有在data段定义了大小的量才是变量。符号常量就相当于C中的宏定义,本质上是一个常量。
PTR操作符
有一个16bit的存储空间,名字为space。在读取数据的时候,可以将它理解为一个16bit的数据:
1 | MOV AX,WORD PTR space |
也可以把它理解为两个8bit的数据:
1 | MOV AL,BYTE PTR space |
数据传送指令
MOV指令
MOV指令需要遵循的规则:
- 两个操作数的尺寸必须一致。
- 两个操作数不能同时为内存操作数。中间可以通过寄存器暂存。
- 目的操作数不能是CS,EIP和IP。
- 立即数不能直接送至段寄存器。要取段地址,使用SEG关键词。
XCHG指令
含义:exchange data,交换两个操作数的内容。
注意:交换两个内存中操作数,需要将一个操作数移到寄存器中。
直接寻址
使用内存地址去内存中寻找操作数。
1 | MOV al,arrayB |
寄存器间接寻址
间接操作数可以是任何用方括号括起来的16位通用寄存器,AX,BX,CX,DX,SI,DI,BP,SP。
实地址模式下只能使用SI,DI,BX,BP。通常尽量避免使用BP,因为BP常用来寻址堆栈而不是数据段。
PTR与间接操作数的联合使用:
1 | INC [SI];error:operand must have size |
寄存器相对寻址
形如:
1 | MOV AL,[Array+SI] |
实模式下只能使用SI,DI,BX,BP寄存器,同时要尽量避免使用BP寄存器。
加法和减法
INC和DEC指令
格式:
1 | INC reg/mem |
注意:INC和DEC指令不影响进位标志。
ADD指令
将同尺寸的源操作数和目的操作数相加,结果在目的操作数中,不改变源操作数。
格式:
1 | ADD 目的,源 |
SUB指令
将源操作数从目的操作数中减掉,结果在目的操作数中,不改变源操作数。
格式:
1 | SUB 目的,源 |
影响标志位:CF、ZF、SF、OF、AF、PF
NEG指令
含义:negate,求负
格式:
1 | NEG reg/mem |
影响标志位:CF、ZF、SF、OF、AF、PF
算术运算影响的进位标志
ZF和SF
注意符号位,为正数则SF=0,为负数则SF = 1。
CF
注意,若在第二种情况中,如下写法,则CF= 1。即目的操作数为AL而不是AX。
1 | MOV AL,0FFH |
溢出标志
OF = $C_n\oplus C_{n-1}$,其中,$C_n$为符号位产生的进位,即标志位CF;$C_{n-1}$为最高有效位符号位产生的进位。
CPU如何知道一个数字是有符号的还是无符号的?
- CPU并不知道——只有程序员才知道。
- CPU在执行指令之后机械地设置各种状态标志,它并不知道哪些对程序员是重要的,程序员自己来选择解释哪些标志和忽略哪些标志。
JMP和LOOP指令
控制转移可分为两种:
- 无条件转移:以JMP指令为例。
- 条件转移:以LOOP指令为例。
LOOP指令
格式:
1 | LOOP 目的地址 |
在实地址模式下,用做默认循环计数器的是CX而不是ECX。
循环的目的地址与当前地址只能在相距-128到+127字节的范围之内。
循环的嵌套格式:
1 | L1: |
布尔和比较指令
AND指令
功能:在操作数的对应数据位之间执行布尔(位)”与“操作,并将结果保存在目的操作数中。
格式:
1 | AND 目的,源 |
两个操作数可以是8bit,或16bit,但它们的尺寸必须相同。
影响的标志位:
- 总是清除OF和CF;
- 根据结果修改SF、ZF、PF。
主要用途:对特定的位清”0“,同时保留其它的位。
OR指令
功能:按位取“或”。
格式:与AND指令相同。
主要用途:对特定位置“1”,并保留其他位。
例:将0到9之间的整数转换成对应的ASCII码数字。方法:将位4和位5设置为1.
XOR指令
功能:按位取“异或”。
格式:与AND及OR指令相同。
用途:
- 对某些位按位取反(与1做异或),同时不影响其他的位。
- 判断16位或32位值的奇偶性。和0异或,看PF标志位。
- 简单数据加密。
NOT指令
功能:将操作数所有数据位取反,结果为反码。
格式:
1 | NOT reg |
NOT指令不影响任何状态标志。
TEST
功能:两操作数按位“与”,根据结果设置标志位,但不回送结果(不修改目的操作数)。
格式:与AND指令相同。
用途:测试操作数的某一位是“0”还是“1”。
例如,测试AL中低0位、第3位是否同时为“0”。
1 | test al,00001001b |
然后判断ZF是否等于1。
影响的标志:清除OF、CF;修改SF、ZF、PF。
CMP指令
格式:与AND指令相同