IA-32汇编语言笔记(3)—— 简单传送、加减指令 & 标志寄存器

  • 记录汇编语言课笔记,可能有不正确的地方,欢迎指出
  • 教材《新概念汇编语言》—— 杨季文
  • 这篇文章对应书第二章 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	//EAX =	12345678H
MOV	EBX, EAX		//EBX =	12345678H
MOV	ESI, 256		//ESI =	00000100H 
MOV	ECX, -1			//ECX =	FFFFFFFFH
MOV	BX, ‘b’			//EBX =	12340062H
MOV	AH, AL			//EAX =	12347878H
MOV	CX, AX			//ECX =	FFFF7878H
MOV	AX, SI			//EAX =	12340100H
MOV	SI, BX			//ESI =	00000062H
MOV	AL, BH			//EAX =	12340100H

(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          //8位交换
XCHG    SI, BX          //16位交换
XCHG    EAX, EBX        //32位交换

XCHG    AL, [EBX]       //AL与由EBX指定的字节存储单元交换
XCHG    [ESI], BX       //BX与由ESI指定的字存储单元交换
XCHG    EDX, [EDI]      //EDX与由EDI指定的双字存储单元交换

二、加减指令

(1)ADD

名称ADD(加法指令)
格式ADD DEST,SRC
动作把目标DEST和源SRC相加,结果送到目标DEST
合法值SRC:通用寄存器、存储单元、立即数
DEST:通用寄存器、存储单元
注意DEST 和 SRC 必须尺寸一致
ADD指令会影响标志寄存器的值
独立操作寄存器一部分时,进位不会加入未取出的部分(详见下方实例)
  • 示例:
ADD ECX,200		//使ECX加上200
ADD EBX,ECX		//使EBX加上ECX的值
ADD SI,10		//使SI加上10
ADD DH,DL		//使DH加上DL的值
ADD AL,5		//使AL加上5
ADD EAX,[EBX]	//使EAX加上EBX的值指定的存储单元的值

在这里插入图片描述

(2)SUB

名称SUB(减法指令)
格式SUB DEST,SRC
动作把目标DEST减去源SRC,结果送到目标DEST
合法值SRC:通用寄存器、存储单元、立即数
DEST:通用寄存器、存储单元
注意DEST 和 SRC 必须尺寸一致
SUB指令会影响标志寄存器的值
独立操作寄存器一部分时,借位不会影响未取出的部分
  • 示例:
SUB    EDX,1000       //使EDX减去1000
SUB    ESI,EBX        //使ESI减去EBX值
SUB    DI,20          //使DI减去20
SUB    DH,CL          //使DH减去CL值
SUB    AL,7           //使AL减去7
SUB    ECX,[EDI]      //使ECX减去由EDI指定的双字存储单元值

(3)INC

名称INC(加1指令)
格式INC DEST
动作对DEST加1后送回DEST,可以是字节//双字
合法值DEST:通用寄存器、存储单元
注意这条指令不影响标志寄存器中的进位标志,但会影响其他状态标识
  • 示例:
INC    ESI 	//使寄存器ESI值加1
INC    DI   //使寄存器DI值加1
INC    CL   //使寄存器CL值加1

(4)DEC

名称DEC(减1指令)
格式DEC DEST
动作对DEST减1后送回DEST,可以是字节//双字
合法值DEST:通用寄存器、存储单元
注意这条指令不影响标志寄存器中的进位标志,但会影响其他状态标识
  • 示例:
DEC   EDI     //使寄存器EDI值减1
DEC   SI      //使寄存器SI值减1
DEC   AL      //使寄存器AL值减1

(5)NEG

名称NEG(取补指令)
格式NEG OPRD
动作用0减去OPRD,取得其负数,结果送回OPRD
合法值OPRD:通用寄存器、存储单元
注意操作数OPRD是以补码表示
MOV   AL,3       //AL=03H
NEG   AL         //AL=FDH(-3)
MOV   EDX,-5     //EDX=FFFFFFFBH
NEG   EDX        //EDX=00000005H

(6)ADC (带进位加)

名称ADC (带进位加)
格式ADC DEST,SRC
动作DEST=DEST+SRC+CF
合法值DEST:通用寄存器、存储单元
SRC:通用寄存器、存储单元、立即数
注意DEST 和 SRC 必须尺寸一致
ADC指令会影响标志寄存器的值
独立操作寄存器一部分时,进位不会加入未取出的部分。和ADD的区别,仅在于求和结果中会加上当前CF标志的值
/*
dp26
	利用带符号加法ADC,处理可能产生的进位
*/

#include<stdio.h>

int main()
{
	unsigned char v1 = 188, v2 = 172, v3 = 233;	//3个字节变量
	unsigned int sum = 0;

	_asm
	{
		XOR EDX,EDX			//EDX清零,DX用于存放累加和
		ADD DL,v1			//加第一个字节
		ADC DH,0			//高8位相加

		ADD DL, v2			//加第二个字节
		ADC DH, 0			//高8位相加(意在处理进位)
		
		ADD DL, v3			//加第三个字节
		ADC DH, 0			//高8位相加(意在处理进位)

		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		//AX=06FFH, CF=1
SBB AH,2		//AX=03FFH,CF=0	(注意这里CF的影响)
SBB AH,2		//AX=01FFH,CF=0

三、标志寄存器及使用

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)运算
//以下代码演示PF和AF作用
MOV EAX,6			//EAX=0000 0006H,PF和AF无变化
ADD EAX,5			//EAX=0000 000BH,	PF=0,(0x0B = 0000 1011)		AF=0 	
ADD EAX,7			//EAX=0000 0012H,	PF=1,(0x12 = 0001 0010)		AF=1	
ADD EAX,10000008H	//EAX=1000 001AH,	PF=0,(0x1A = 0001 1010)		AF=0	
ADD EAX,9			//EAX=1000 0023H,	PF=0,(0x23 = 0010 0011)		AF=1 	

(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操作指令

指令作用
CLC清CF
STC置CF
CMCCF取反
MOV	AX, 8899H	//AX = 8899H
ADD	AL, AH		//AX = 8821H  CF=1 (发生进位)
CLC				//CF=0
STC				//CF=1
CMC				//CF=0
CMC				//CF=1

(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			//SF=ZF=PF=AF=CF=0
		LAHF			
		MOV flag1,AH	//把志寄存器低8位的值保存

		MOV DX,7799H
		ADD DL,DH       //把DH加到DL,77H+99H=110H。		AF=1,CF=1	(最低四位和第3位都发生进位;出现进位)
		LAHF
		MOV flag2, AH	//把志寄存器低8位的值保存

		SUB DH,84H		//DX=F310H。					SF=1,CF=1,PF=1(DH减法溢出,最高位为1;出现借位;F3=1111 0011有偶数个1)
		CLC				//								CF=0
		LAHF
		MOV flag3, AH	//把志寄存器低8位的值保存
	}
	printf("flag1=%02XH\n", flag1);			//显示为02H -> 0000 0010
	printf("flag2=%02XH\n", flag2);			//显示为13H -> 0001 0011
	printf("flag3=%02XH\n", flag3);			//显示为86H -> 1000 0110
	
	system("pause");
	return 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云端FFF

所有博文免费阅读,求打赏鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值