《汇编语言》—— 王爽 第11章笔记及实验11

第11章 标志寄存器

标志寄存器是一种特殊的寄存器,具有以下3种作用:

  • 用来存储相关指令的某些执行结果:
  • 用来为CPU执行相关指令提供行为依据;
  • 用来控制CPU的相关工作方式。

以下简称为flag,flag是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。

在这里插入图片描述

ZF标志

位于flag第6位,零标志位

如果相关指令执行结果为0,那么zf=1,如果不为0,则zf=0

mov ax,1
sub ax,1
;zf=1
mov ax,2
sub ax,1
;zf=0

那么任何指令都会影响到zf吗?答案是否定的。

在8086CPU的指令集中,有的指令的执行是影响标志寄存器的,比如,dd、 sub、mul、div、inc、or、and等,它们大都是运算指令(进行逻辑或算术运算);有的指令的执行对标志寄存器没有影响,比如,mov、push、pop等,它们大都是传送指令。在使用一条指令的时候,要注意这条指令的全部功能,其中包括,执行结果对标志寄存器的哪些标志位造成影响。

PF标志

位于flag第2位,奇偶标志位

如果相关指令执行结果的所有bit位中1的个数是偶数,pf=1,如果是奇数,那么pf=0.

mov al,1
add al,10
;结果为1011b,奇数个1,pf=0
mov al,1
or al,2
;结果为11b,偶数个1,pf=1

SF标志

位于flag第7位, 符号标志位.

相关指令执行结果为负, sf=1, 如果非负, sf=0

只有我们把影响sf的相关指令视为有符号数运算时, sf的值才是有意义的.

我们可以说sf把每个数都视为有符号的, 只不过实际意义上并不一定.

CF标志

位于flag第0位, 进位标志位.

在进行无符号数运算时, 它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值.

OF标志

位于flag第11位, 一般情况下, OF记录了有符号数运算的结果是否发生了溢出.

如果发生溢出, OF=1, 如果没有, OF=0.

adc 指令

adc是带进位加法指令

功能: 操作对象1 = 操作对象1 + 操作对象2 + CF

简而言之, adc 比 add 指令 多加了一个 CF.

在这里插入图片描述

不能取代, 因为add si,2 add di, 2肯定不会进位, 导致CF一直是0.

sbb指令

同上, sbb是带借位减法指令

功能: 操作对象1 = 操作对象1 - 操作对象2 - CF

通过sbb可以实现和adc类似的功能.

cmp指令

cmp指令相当于减法指令, 但是不保存结果, 也就是不会改变被减数大小, 它只会对标志寄存器产生影响.

对于cmp ax,bx

在这里插入图片描述

反过来说, 我们可以根据标志寄存器判断ax和bx的大小关系.
在这里插入图片描述

-对于有符号运算

在这里插入图片描述

在这里插入图片描述

检测比较结果的条件转移指令

“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改P。

[!NOTE]

重新理解一下jcxz的语义, “j"显然代表"jump(转移)”, 那么接下来就是条件了.

jcxz的转移条件是cx=0, 不难想到cxz的意思就是**“cx = z(ero)”**.

既然有了"cxz", 也就有其他类似的条件转移指令.

大多数条件转移指令都检测标志寄存器的相关标志位, 它们都与cmp指令密切相关.

在这里插入图片描述

在这里插入图片描述

示例程序: 统计data段中数值为8的字节的个数, 用ax保存统计结果.

mov ax,data
mov ds,ax
mov bx,0	;ds:bx指向第一个字节
mov ax,0	;初始化累加器
mov cx,8
S:
cmp byte ptr[bx],8;和8进行比较
jne next	;如果不相等转到next,继续循环
inc ax	;如果相等就将计数值加1
next:inc bx
loop s
;程序执行后:(ax)=3

;这个程序也可以写成这样:
mov ax,data
mov ds,ax
mov bx,0	;ds:bx指向第一个字节
mov ax,0	;初始化累加器
mov cx,8
S:
cmp byte ptr [bx],8	;和8进行比较
je ok	;如果相等转到ok
jmp short next	;如果不相等就转next,继续循环
ok:
inc ax	;如果相等就将计数值加1
next
inc bx
loop s

第二个示例虽然更符合题目的语义, 但是多使用了一个标志, 不如第一个示例简洁, 这种逆向思考的思维值得学习.

DF标志和串传送指令

位于flag第10位,方向标志位,在串处理指令中,控制每次操作后si、di的增减

  • df=0 每次操作后si、di递增;
  • di=1 每次操作后si、di递减。
-movsb指令

将ds:si指向的内存单元中的字节送入es:di中, 然后根据df的值将si和di递增或递减.

-movsw指令

movsb操作byte(字节), movsw操作word(字), 而且si和di递增2或递减2.

-rep指令

一般来说,movsb和movsw都和rep配合使用, 格式如下:

rep movsb

类似于

s:	movsb
	loop s

也就是执行cx次movsb, rep movsb可以循环实现(cx)个字符的传送.

-cld,std

既然df决定着movsb(w)执行的方向, 所以CPU提供了相应的指令来设置df位:

cld指令: df = 0

std指令: df = 1

用串传送指令,将F000H段中的最后16个字符复制到data段中.

data segment
	db 16 dup (0)
data ends

code segment
start:
	mov ax, 0f000h
	mov ds, ax
	mov si, 0ffffh
	mov ax, data
	mov es, ax
	mov di, 15
	std
	mov cx, 16		;mov cx,8
	rep movsb		;rep movsw 同理	   

	mov ax, 4c00h
	int 21h

code ends
end  start

pushf 和 popf

pushf 将标志寄存器的值压栈, popf从栈中弹出数据, 送入标志寄存器中.

实验11

在这里插入图片描述

assume cs:code, ds:data

data   segment
	db "Beginner's All-purpose Symbolic Instruction Code.",0
data ends

code segment
start:
	mov  ax, data
	mov  ds, ax
	mov  si, 0
	call letterc

	mov ax, 4c00h
	int 21h

letterc:
	push si
	mov  ch, 0
convert:
	mov  cl,   [si]
	jcxz done
	cmp  cl,   97
	jb   next       ;小于a的ascii值
	cmp  cl,   122
	ja   next       ;大于z的ascii值
	
	;符合要求,转换为大写,-32
	mov  al,   32
	sub  cl,   al
	mov  [si], cl

next:;进入下个循环
	inc si
	jmp short convert

done:;循环结束
	pop si
	ret

code ends
end  start
-结果

在DEBUG中查看转换结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值