[汇编原理 IBM-PC] 串循环指令/循环指令LOOP/子程序

串处理指令

前言

串处理指令一般与REP指令配合。 因为串操作指令其实只是对“串”主要就体现在REP上

REP是前缀,但它不是伪指令,REP有具体功能,它可以判断CX是否为0,还可以执行CX=CX-1
CX的递减不影响标识位

CLD(CLear Directionflag)则是清方向标志位,也就是使DF的值为0,在执行串操作时,使地址按递增的方式变化,这样便于调整相关段的的当前指针。这条指令与STD(SeT Direction flag)的执行结果相反,即置DF的值为1

串指令一般为两大类

1与REP 相配合的MOVS LODS STOS INS OUTS指令

格式一般为:REP 指令
执行的操作:
1.先判断CX(计数寄存器)是否为0,如果为0,则退出循环
2.CX减一
3.执行MOVS等串指令
4.重复1~3的步骤

1.1 MOVS 串传送指令

常见格式:
1.MOVSB (字节操作) MOVSW(字操作)
实际上执行的是

  • 1、将数据段DS的源变址寄存器SI指向的数据段的内容传送到 附加段ES的目的变址寄存器指向的附加段的内容当中
  • 2、根据方向标志位DF 相应修改 源变址寄存器SI 和目的变址寄存器 DI(也就是修改地址,进行下一次操作的准备)
  • 3、DF=0:SI、DI增加1,DF=1:SI、DI减1(字节操作,如果是字操作,则相应增加2,减2)

REP MOVS 串传送指令的使用

  • 1、把数据段的源串的首地址放入源变址寄存器当中(如果方向相反的话,则放末地址)
  • 2、把附加段将要存放数据串的首地址放入目的变址寄存器当中(方向相反,同理)
  • 3、把源串的长度放入计数寄存器当中(设置循环次数CX)
  • 4、设置方向
    例题:
    3.70:
    在数据段中有一个字符串,其长度为17,要求把它们送到附加段中的一个缓冲区
> data segment
> 		mess1 db 'personal computer $'
> data ends
>  
>  extra segment
>  	mess2 db 17 dup(?)
>  extra ends 
>   
>   code segment
>  	assume ds:data,es:extra
>  	mov ax,data
>  	mov ds,ax
>  	 
>  	mov ax,extra
>  	mov es,as
>  	lea si,mess1
>  	lea di,mess2
>  	mov cx,17
>  	cld
>  	rep movsb
>    code ends
1.2 STOS 存入串操作

STOS指令一般用来初始化(并且是初始化附加段的)
常见格式
LODSB (字节操作) LODSW(字操作)
实际上操作的两个默认的寄存器是:AX与DI
执行的操作为:

  • 1.把AL(字节操作)/AX(字操作)的内容存入到目的寄存器指向的附加段的某单元中
  • 2、根据方向标志位更改目的寄存器的地址

与REP连用的应用
例题
3.71 如果要把附加段的首五个字节缓冲区置为20H

MOV CX,5
MOV AL,20H
MOV DI,0H
CLD
REP STOSB
1.3 LODS从串取指令

常见格式:
LODSB (字节操作) LODSW(字操作)
默认的两个寄存器位AX与SI
执行的操作位:

  • 1、把源变址寄存器指向的单元内容送到AX/AL中,分别取决于字操作和字节操作
  • 2、根据方向标志和数据类型修改源变址寄存器的内容(也就是修改地址)

由于操作都是传送到同一个单元AX/AL中,因此一般不与REP连用
总结:STOS和LODS都是与AX寄存器相关的STOS是存储到ES段中,因此相应的寄存器是DI(目的变址寄存器),而LODS是取出,因此相应的寄存器是SI(源变址寄存器)

1.4 INS和OUTS

这两个与STOS/LODS很类似,只是与外部设备进行数据交换的
INSB 与INSW

  • 1、指令是把I/O空间的字节/字传送到附加段目的变址寄存器所指向的存储单元中
  • 2、根据DF的值以及数据类型修改目的变址寄存器
    而使用DX存放端口号,相当于I/O空间的地址
    因此操作:((DX))–>((DI))
    再改变DI寄存器的内容

OUTSB OUTSW

  • 1、把源变址寄存器所指向的数据段的字节/字单元送到DX端口号的I/O空间中
  • 2、根据DF的值,以及数据类型修改SI的大小

2与REPZ/REPE 和REPNZ/REPNE联合工作的CMPS SCAS指令

REPZ/REPE:repeat while 相等或为0时
也就是重复串操作的条件除了CX不等于0,另外一个得满足的条件是ZF=1
执行的操作为:

  • 1、判断:若CX=0或者ZF=0(注意这里的ZF=0是不等于0.
  • 2、CX减1
  • 3、执行后面的串操作
  • 4、重复1~3

与REPE/REPZ和REPNE/REPNZ联合工作的串比较指令CMPS和SCAS

关键在于CX=0是退出条件,CX不能体现字符串比较出的结果,CX=0只能说明每一个都比完了,至于结果,结果唯一的条件就是ZF
执行的操作是先判断CX是否为0,ZF是否为0,CX=0,ZF=0两个条件满足一个就退出。否则继续向下,CX=CX-1,执行其后的串指令。
重复上述过程。
REPE和REPZ是完全相等的同义词!两者可以随意相互替换。REPE/REPZ——相等则重复

REP循环指令都是while-do,先判断条件再执行,并且cx的递减都不会影响标志位

在这里插入图片描述

2.1 CMPS 串比较指令

CMPSB CMPSW

  • 1.指令把源变址寄存器指向的数据段的一个字节/字单元与目的变址寄存器指向的附加段一个字节/字单元相减,但并不保存结果,只改变标志位
  • 2、根据DF与数据类型改变源变址寄存器和目的变址寄存器
    用源串中的一个字节(或者字)减去目的串中的一个字节(或者字)
    因为做了减法,结果很显然会对标志寄存器产生影响,如果结果为0,ZF标志位会等于1
2.2 SCAS 串扫描指令

与CMPS类似,只是CMPS是串之间的比较,而SCAS是一个串的扫描(比如寻找这个串的某个值),都是执行相减的操作

  • 1、指令将AL/AX的内容与目的变址寄存器指向的附加段的字节/字单元内容相减,同样不保存结果,只根据结果设置标志位
  • 2、根据DF和数据类型修改目的变址寄存器
2.3 CMPS/SCAS两个串指令与REPZ/REPE/REPNZ/REPNE结合,用来比较两个数据串或者从一个字符串中寻找一个指定的字符

LOOP循环指令

loop指令的格式是:loop 标号

cpu执行loop指令的时候,要进行两步操作

step 1:(cx)=(cx)-1

step 2:判断cx中的值,不为零则转至标号处执行,如果为零,则执行loop指令后面的内容
LOOPZ
在step2时跳转条件位CX!=0并且ZF=0
LOOPNZ
在step2时跳转条件为CX!=0并且ZF=1

LOOP和REP循环的细节

LOOP是先cx减一然后再判断cx是否为0,而REP是先判断cx是否为0,然后再减一。
也就是loop做的是do while,而rep做的是while-do

子程序

子程序分为:
(1)段内直接调用/段内间接调用
段内直接近调用CALL DST
执行的步骤为:

(1)先把CALL调用指令(不是子程序)的下一条指令的地址存入堆栈中(是为了返回主程序继续顺序执行)
(2)转移到子程序的入口地址,执行子程序的命令
实际的指令为
PUSH IP(而IP的内容存的都是下一条指令的地址,不是当前执行指令的地址)
(IP)+D16–>(IP):事实上(指令中DST给出的转向地址即子程序的入口地址),D16是转向地址与当前地址的差值(即位移量)

段内间接近调用CALL DST
指令中的DST可使用寄存器寻址方式或任一种存储器寻址方式,由指定的寄存器寻址方式或存储器的内容给出转向地址
执行的逻辑与段内直接近调用一样
具体的指令为:

PUSH IP
有效地址–>(IP)

事实上段内两种调用方式均为近调用,因此转向地址中只包含其偏移地址的部分,段地址是保持不变的
(2)段间直接远调用/段间间接远调用
段间直接远调用
直接给指令了:

PUSH CS
PUSH IP
DST指定的偏移地址–>(IP)
DST的段地址–>(CS)

值得注意的是:段地址放在高地址位,因此先入栈
段间间接远调用

PUSH CS
PUSH IP
(EA)–>(IP)
(EA+2)–>(CS)

其中EA是由DST的寻址方式确定的有效地址,这里可以用任一种存储器寻址方式来取得EA值。在这里插入图片描述

在这里插入图片描述

习题

在这里插入图片描述

	MOV AL,'&'
	MOV CX,18
	CLD
	;注意SCAS是目的变址寄存器
	MOV DI,SEG STRING;返回变量或者标号的段地址值
	MOV ES,DI;赋给ES附加段寄存器
	LEA DI,STRING;获得偏移地址
	REPNZ SCASB
	JNZ EXIT
	DEC DI,1
	MOV ES:BYTE PTR [DI],' '
EXIT:
	INT 20H

在这里插入图片描述

公共的程序段如下:
	MOV DI,SEG PAINT_LINE
	MOV ES,DI
(1)
	MOV CX,132
	MOV AL,' '
	CLD
	LEA DI,PARINT_LINE
	REP STOSB
 (2)
 	MOV CX,9
 	MOV AL,'-'
 	CLD
 	LEA DI,STUDENT_ADDR
 	REPNZ SCASB;注意SCASB和CMPS都是使用REPZ/REPNZ
 	JNZ NO_FOUND;没找到,跳转即可
 	DEC DI;SCASB会自动增加,这里是BYTE,因此减1
 (3)
 	MOV CX,9
 	MOV AL,'-'
 	STD 
 	LEA DI,STUDENT_ADDR
 	ADD DI,9-1
 	REPNZ SCASB
 	JNZ NO_FOUND
 	INC DI
 (4)
 	MOV CX,30
 	MOV AL,' '
 	CLD
 	LEA DI,STUDENT_NAME
 	REPZ SCASB
 	JNZ NOT
 	MOV AL,'*'
 	MOV CX,30
 	CLD 
 	LEA DI,STUDENT_NAME
 	REP STOSB
 (5)
 	
 	MOV SI,SEG STUDENT_NAME
 	MOV DS,SI
 	LEA SI,STUDENT_NAME
 	MOV CX,30
 	LEA DI,PRINT_LINE
 	CLD
 	REP MOVSB
	MOV CX,9
 	STD
 	MOV SI,STUDENT_ADDR
 	ADD SI,9-1
 	MOV DI,PRINT_LINE
 	ADD DI,132-1
 	REP MOVS

在这里插入图片描述
注意这类题需要写成二进制,不然容易犯错
(1)
1478H=0001 …(正) BX=1000 …(你可能感觉这个80DCH是正数,实际上是负数,第一位大于等于8就为负数了)
(AX)+(BX)=负 (正加负=负)因此没有带符号的溢出
L1
(2)
B568H(负) 42C8H(正)
(AX)+(BX)= 正(负加正=正:带符号没有溢出)
L1
(3)
42C8H=正 608DH(正)
(AX)+(BX)=负(带符号的溢出),然而若是无符号数则没有溢出
L2
(4)
D023H=负 9FD0H(负)
(AX)+(BX)=6FF3H(带符号溢出,同时无符号溢出)
同时(AX)=6FF3H(正) (BX)=9FD0H(负)
(AX)-(BX)=D…(负)(带符号溢出,同时无符号溢出(有借位了))
L5
(5)
负+负=正(带符号溢出,无符号溢出)
此时(AX)=4A14H
正-负=负(带符号/无符号同时溢出)
L5

这题还有一个很坑的是,JNO没有溢出才跳转,多注意!!我看到就像转no
在这里插入图片描述

这种题只需要记住关键的转移指令就行,B和A是一对(分别是Below和Above代表着无符号数),而G和L是一对(分别代表着Greater和less 代表着带符号数)。E则是Equal等于的意思
可以参考里面的移位指令
无符号数:JB(小于) JNB(大于等于)JBE(小于等于)JNBE(大于)
带符号数:JL(小于)JNL(大于等于)JLE(小于等于)JNLE(大于)
这里还得提一句,如果你直接看带符号数的话,记住只要第一位大于8(1000),那么就是负数了
(1)这明显是等于,因此带等于都行
JNB JBE JNL JLE
(2)还是等于
JNB JBE JNL JLE
(3)这里带符号数 是一正一负,因此很好判断带符号数的大小,我的建议是,如果是两个负数,那么还是转成原码比较。
无符号数是大于(大于等于都是行的),带符号数是小于
JNB JNBE JL JLE
(4)同样这里是一正一负
无符号数大于,带符号数大于
JNB JNBE JNL JNLE
(5)FFC5H转成原码(正数原码补码相同的)为1000 0000 0011 1011 FF8BH转成原码为:1000 0000 01111 0101 FFC5H更大(绝对值更小)
无符号数大于,带符号数大于
JNB JBE JNL JNLE
(6)带符号数一个正数一个负数
无符号小于,带符号大于
JB JBE JNL JNLE
(7)无符号小于,带符号数小于
JB JBE JL JLE
(8)一负一正
JNB JNBE JL JLE

在这里插入图片描述
比较简单,不赘述了
在这里插入图片描述
在这里插入图片描述

这题需要理清思路

	MOV AL,STATUS
	AND AL,00010101B
	JZ ROUTINE_4
	JPE ROUTINE_2
	SUB AL,00010101B
	JZ ROUTINE_1
ROUTINE_3:
	JMP EXIT
ROUTINE_2:
	JMP EXIT
ROUTINE_1:
	JMP EXIT
ROUTINE_4:
	JMP EXIT
EXIT:
	INT 20H	

在这里插入图片描述
在这里插入图片描述
(1)(AX)=5H (BX)=10H(CX)=0 (DX)=0
(2)(AX)=2H(BX)=4H(CX)=3H(DX)=1H
(3)(AX)=3H(BX)=7H(CX)=2H(DX)=0
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值