- 记录汇编语言课笔记,可能有不正确的地方,欢迎指出
- 教材《新概念汇编语言》—— 杨季文
- 这篇文章对应书第二章 IA32处理器基本功能 2.2.2~2.3.4部分
一、简单传送指令
(1)MOV
名称 | MOV(传送指令) |
---|
格式 | MOV DEST,SRC |
动作 | 把一个 字节/字/双字 从SRC移动到DEST |
合法值 | SRC:通用寄存器、存储单元、立即数; |
| DEST:通用寄存器、存储单元 |
注意 | SRC 和 DEST必须尺寸一致 |
| SRC 和 DEST不可同时是存储单元,即两个存储单元之间不能直接传送数据 |
| 对于SRC为立即数的情形,如果其长度大于DEST,将会截取低位赋值到DEST;如果其长度小于DEST,将会在DEST高位补零 |
- CPU只能操作CPU寄存器中的数据,对于存储单元中数据的移动,也需要先把数据读取到CPU寄存器中。如果DEST 和 RSC同时为存储单元,CPU就不知道该把数据取到哪个寄存器中了。因此SRC 和 DEST不可同时是存储单元
- 示例:
MOV EAX, 12345678H
MOV EBX, EAX
MOV ESI, 256
MOV ECX, -1
MOV BX, ‘b’
MOV AH, AL
MOV CX, AX
MOV AX, SI
MOV SI, BX
MOV AL, BH
(2)XCHG
名称 | XCHG(交换指令) |
---|
格式 | XCHG OPDR1,OPDR2 |
动作 | 交换 OPDR1 和 OPDR2 中的值,可以是字节/字/双字 |
合法值 | OPDR1:通用寄存器、存储单元; |
| OPDR2:通用寄存器、存储单元 |
注意 | OPDR1 和 OPDR2 必须尺寸一致 |
| OPDR1 和 OPDR2 不可同时是存储单元 |
| OPDR1 和 OPDR2 中不可以有立即数 |
- CPU只能操作CPU寄存器中的数据,对于存储单元中数据的移动,也需要先把数据读取到CPU寄存器中。如果OPDR1 和 OPDR2同时为存储单元,CPU就不知道该把数据取到哪个寄存器中了。因此OPDR1 和 OPDR2 不可同时是存储单元
- 对于存储单元做参数的指令的情况,会根据另一个参数的尺寸确定从指定地址取出数据的尺寸
- 示例:
XCHG AL, AH
XCHG SI, BX
XCHG EAX, EBX
XCHG AL, [EBX]
XCHG [ESI], BX
XCHG EDX, [EDI]
二、加减指令
(1)ADD
名称 | ADD(加法指令) |
---|
格式 | ADD DEST,SRC |
动作 | 把目标DEST和源SRC相加,结果送到目标DEST |
合法值 | SRC:通用寄存器、存储单元、立即数 |
| DEST:通用寄存器、存储单元 |
注意 | DEST 和 SRC 必须尺寸一致 |
| ADD指令会影响标志寄存器的值 |
| 独立操作寄存器一部分时,进位不会加入未取出的部分(详见下方实例) |
ADD ECX,200
ADD EBX,ECX
ADD SI,10
ADD DH,DL
ADD AL,5
ADD EAX,[EBX]
(2)SUB
名称 | SUB(减法指令) |
---|
格式 | SUB DEST,SRC |
动作 | 把目标DEST减去源SRC,结果送到目标DEST |
合法值 | SRC:通用寄存器、存储单元、立即数 |
| DEST:通用寄存器、存储单元 |
注意 | DEST 和 SRC 必须尺寸一致 |
| SUB指令会影响标志寄存器的值 |
| 独立操作寄存器一部分时,借位不会影响未取出的部分 |
SUB EDX,1000
SUB ESI,EBX
SUB DI,20
SUB DH,CL
SUB AL,7
SUB ECX,[EDI]
(3)INC
名称 | INC(加1指令) |
---|
格式 | INC DEST |
动作 | 对DEST加1后送回DEST,可以是字节/字/双字 |
合法值 | DEST:通用寄存器、存储单元 |
注意 | 这条指令不影响标志寄存器中的进位标志,但会影响其他状态标识 |
INC ESI
INC DI
INC CL
(4)DEC
名称 | DEC(减1指令) |
---|
格式 | DEC DEST |
动作 | 对DEST减1后送回DEST,可以是字节/字/双字 |
合法值 | DEST:通用寄存器、存储单元, |
注意 | 这条指令不影响标志寄存器中的进位标志,但会影响其他状态标识 |
DEC EDI
DEC SI
DEC AL
(5)NEG
名称 | NEG(取补指令) |
---|
格式 | NEG OPRD |
动作 | 用0减去OPRD,取得其负数,结果送回OPRD |
合法值 | OPRD:通用寄存器、存储单元, |
注意 | 操作数OPRD是以补码表示的 |
MOV AL,3
NEG AL
MOV EDX,-5
NEG EDX
(6)ADC (带进位加)
名称 | ADC (带进位加) |
---|
格式 | ADC DEST,SRC |
动作 | DEST=DEST+SRC+CF |
合法值 | DEST:通用寄存器、存储单元 |
| SRC:通用寄存器、存储单元、立即数 |
注意 | DEST 和 SRC 必须尺寸一致 |
| ADC指令会影响标志寄存器的值 |
| 独立操作寄存器一部分时,进位不会加入未取出的部分。和ADD的区别,仅在于求和结果中会加上当前CF标志的值 |
#include<stdio.h>
int main()
{
unsigned char v1 = 188, v2 = 172, v3 = 233;
unsigned int sum = 0;
_asm
{
XOR EDX,EDX
ADD DL,v1
ADC DH,0
ADD DL, v2
ADC DH, 0
ADD DL, v3
ADC DH, 0
MOV sum,EDX
}
printf("sum=%u\n", sum);
system("pause");
return 0;
}
(6)SBB (带借位减)
名称 | SBB (带借位减) |
---|
格式 | SBB DEST,SRC |
动作 | DEST=DEST-SRC-CF |
合法值 | DEST:通用寄存器、存储单元 |
| SRC:通用寄存器、存储单元、立即数 |
注意 | DEST 和 SRC 必须尺寸一致 |
| SBB 指令会影响标志寄存器的值 |
| 独立操作寄存器一部分时,进位不会加入未取出的部分。和SUB的区别,仅在于求和结果中会减去当前CF标志的值 |
MOV AX,620H
SUB AL,21H
SBB AH,2
SBB AH,2
三、标志寄存器及使用
1、标志寄存器
- 一个32位寄存器
- 用于反映处理器的状态和运算结果的某些特征
- 可以暂时认为主要是:状态标志 & 控制标志
- 低16位对应8086的FLAGS寄存器
- 特别注意其中有一些位是保留的,恒为定值,下图中灰色的即为保留位
- 用VS调试汇编程序时,如何观察标志寄存器呢,可以参考:这里
2、状态标志
(1)CF 进(借)位标志
名称 | CF (进借位标志) |
---|
值 | CF=1:当算术运算产生进位或者借位 |
| CF=0:没有产生进位或借位 |
用途 | 无符号数运算产生溢出的判据 |
| 比较无符号数大小 |
| 进行多字节数加减运算 |
注意 | 字节运算,最高位为第7位;字运算,最高位为15位;双字运算,最高位为31位 |
| 独立操作寄存器一部分时,进位不会加入未取出的部分 |
(2)ZF 零标志
名称 | ZF (零标志) |
---|
值 | ZF=1:运算结果=0 |
| ZF=0:运算结果!=0 |
用途 | 判断运算结果是否为0(不管有符号还是无符号) |
(3)SF 符号标志
名称 | SF (符号标志) |
---|
值 | SF=1:运算结果的符号位(最高位)= 1 |
| SF=0:运算结果的符号位(最高位)= 0 |
用途 | 判断有符号数正负性 |
| 参与比较有符号数大小 |
(4)OF 溢出标志
名称 | OF (溢出标志) |
---|
值 | OF=1:有符号数加减运算发生溢出 |
| OF=0:有符号数加减运算没有溢出 |
用途 | 参与比较有符号数大小 |
(5)PF 奇偶标志
名称 | PF (奇偶标志) |
---|
值 | PF =1:运算结果的最低字节中1的个数是偶数 |
| PF =0:运算结果的最低字节中1的个数是奇数数 |
用途 | 串行通信奇偶校验 |
(6)AF 辅助进位标志
名称 | AF (辅助进位标志) |
---|
值 | AF =1:运算中第三位或最低4位发生进/借位 |
| AF =0:运算中第三位或最低4位没有发生进/借位 |
用途 | 二进制编码的十进制数(BCD)运算 |
MOV EAX,6
ADD EAX,5
ADD EAX,7
ADD EAX,10000008H
ADD EAX,9
(7)DF 控制标志
名称 | DF (控制标志) |
---|
值 | DF =1:将以递减顺序对数据串中的数据进行处理 |
| DF =0:将以递增顺序对数据串中的数据进行处理 |
用途 | 主要用于控制串操作指令的操作方向 |
(8)IF 中断允许标志
名称 | IF (中断允许标志) |
---|
值 | IF=1:开中断,CPU可响应可屏蔽中断请求 |
| IF=0:关中断,CPU不响应可屏蔽中断请求 |
用途 | 主要用于控制操作系统正常运行 |
(9)TF 陷阱标志
名称 | TF (陷阱标志) |
---|
值 | TF=1:CPU处于单步执行指令的方式 |
| TF=0:CPU正常执行程序 |
用途 | 主要用于调试 |
(10)补充
vs2017里是用后面的形式显示的,但同时也用=指明了当前标志位的值。实验发现显示形式可能不准,但=后的是准的,比如显示PL=1
,实际就是SF=1
3、状态标志操作指令
(1)CF操作指令
MOV AX, 8899H
ADD AL, AH
CLC
STC
CMC
CMC
(2)状态标志操作指令
指令 | 作用 |
---|
LAHF | 把标志寄存器的低8位,送到通用寄存器AH中(注意这里连带保留位什么的一起取出,取出值不只由标志位决定) |
SAHF | 使得状态标志SF、ZF、AF、PF和CF分别成为来自寄存器AH中对应位的值 |
*/
dp25
演示状态操作指令的使用,同时演示如何获取主要的状态标志,其中H后缀代表16进制
·CF进位标志
·ZF零标志
·SF符号标志
·OF溢出标志
·PF奇偶标志
·AF辅助进位标志
*/
#include<stdio.h>
int main()
{
unsigned char flag1, flag2, flag3;
_asm
{
MOV AH,0
SAHF
LAHF
MOV flag1,AH
MOV DX,7799H
ADD DL,DH
LAHF
MOV flag2, AH
SUB DH,84H
CLC
LAHF
MOV flag3, AH
}
printf("flag1=%02XH\n", flag1);
printf("flag2=%02XH\n", flag2);
printf("flag3=%02XH\n", flag3);
system("pause");
return 0;
}