前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【汇编语言】标志寄存器(四) —— 一行代码,两种世界:标志寄存器的方向标志位,栈操作,Debug中的表示

【汇编语言】标志寄存器(四) —— 一行代码,两种世界:标志寄存器的方向标志位,栈操作,Debug中的表示

作者头像
Crossoads
发布2024-12-29 09:06:28
发布2024-12-29 09:06:28
15500
代码可运行
举报
文章被收录于专栏:汇编语言汇编语言
运行总次数:0
代码可运行

前言

📌 汇编语言是很多相关课程(如数据结构、操作系统、微机原理)的重要基础。但仅仅从课程的角度出发就太片面了,其实学习汇编语言可以深入理解计算机底层工作原理,提升代码效率,尤其在嵌入式系统和性能优化方面有重要作用。此外,它在逆向工程和安全领域不可或缺,帮助分析软件运行机制并增强漏洞修复能力。 本专栏的汇编语言学习章节主要是依据王爽老师的《汇编语言》来写的,和书中一样为了使学习的过程容易展开,我们采用以8086CPU为中央处理器的PC机来进行学习。

1. DF 标志和串传送指令

1.1 DF 标志

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

  • DF = 0:每次操作后si,di递增;
  • DF = 1:每次操作后si,di递减。

1.2 串传送指令

我们再来看下面的一个串传送指令。

汇编语言中的串传送指令用于一次性处理多个数据单元,如MOVS指令可直接完成源和目标之间的数据传输。这类指令简化了对连续数据的操作,尤其适合字符串或数组的处理,提高了代码的简洁性和执行效率。

1.2.1 字节串传送
  • 格式:movsb
  • 功能:执行 movsb 指令相当于进行下面几步操作(以字节为单位传送)。
    • (1)((es)×16 + (di)) = ((ds) ×16 + (si))
    • (2)如果DF = 0则:(si) = (si) + 1,(di) = (di) + 1
    • (3)如果DF = 1则: (si) = (si) - 1,(di) = (di) - 1

用汇编语法描述 movsb 的功能如下。

代码语言:javascript
代码运行次数:0
复制
mov es:[di],byte ptr ds:[si]	;8086并不支持这样的指令,这里只是个描述

如果 df=0:
inc si
inc di

如果 df=1:
dec si
dec di

可以看出,movsb 的功能是将 ds:si 指向的内存单元中的字节送入 es:di中,然后根据标志寄存器DF位的值,将 si和di递增或递减。

1.2.2 字串传送

当然,也可以传送一个字,指令如下。

  • 格式:movsw
  • 功能:将 ds:si指向的内存字单元中word送入es:di中,然后根据标志寄存器DF位的值,将si和di递增2或递减2(以字为单位传送)。

用汇编语法描述 movsw 的功能如下。

代码语言:javascript
代码运行次数:0
复制
mov es:[di],word ptr ds:[si]	;8086并不支持这样的指令,这里只是个描述

如果 df=0:
add si,2
add di,2

如果 df=1:
sub si,2
sub di,2

1.3 与rep配合使用的串传送

movsb和movsw进行的是串传送操作中的一个步骤,一般来说,movsb 和 movsw 都和rep配合使用。

1.3.1 rep movsb

格式如下:

代码语言:javascript
代码运行次数:0
复制
rep movsb 

用汇编语法来描述rep movsb的功能就是:

代码语言:javascript
代码运行次数:0
复制
s:  movsb
	loop s

可见,rep的作用是根据cx的值,重复执行后面的串传送指令。

由于每执行一次movsb指令,si和di都会递增或递减指向后一个单元或前个单元,则rep movsb就可以循环实现(cx)个字符的传送。

1.3.2 rep movsw

同理,也可以使用这样的指令:rep movsw

相当于:

代码语言:javascript
代码运行次数:0
复制
s:  movsw
	loop s

1.4 设置DF位

由于flag的DF位决定着串传送指令执行后,si和di改变的方向,所以CPU应该提供相应的指令来对DF位进行设置,从而使程序员能够决定传送的方向。

8086CPU提供下而两条指令对DF位进行设置:

  • cld指令:将标志寄存器的DF位置0
  • std指令:将标志寄存器的DF位置1

1.5 例题演示与巩固

1.5.1 问题一

编程:用串传送指令,将data段中的第一个字符串复制到它后面的空间中。

代码语言:javascript
代码运行次数:0
复制
data segment
	db ‘Welcome to masm!’
	db  16 dup (0)
data ends
1.5.2 问题一的分析与程序实现

分析:

我们分析一下,使用串传送指令进行数据的传送,需要给它提供一些必要的信息,它们是:

  • ① 传送的原始位置:ds:si;
  • ② 传送的目的位置:es:di;
  • ③ 传送的长度:cx;
  • ④ 传送的方向:DF。

在这个问题中,这些信息如下:

  • ① 传送的原始位置:data:0;
  • ② 传送的目的位置:data:16;
  • ③ 传送的长度:16;
  • ④ 传送的方向: 因为正向传送(每次串传送指令执行后,si和di 递增)比较方便,所以设置DF=0。

编写程序:

好了,明确了这些信息之后,我们来编写程序,如下。

代码语言:javascript
代码运行次数:0
复制
mov ax,data
mov ds,ax
mov si,0       	  ;ds:si指向data:0
mov es,ax
mov di,16     	  ;es:di指向data:16
mov cx,16  	 	  ;(cx)=16,rep循环16次
		
cld               ;设置DF=0,正向传送
rep movsb
1.5.3 问题二

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

代码语言:javascript
代码运行次数:0
复制
data segment
	db 16 dup (0)
data ends
1.5.4 问题二的分析与程序实现

分析:

我们还是先来看一下应该为串传送指令提供什么样的信息。

要传送的字符串位于F000H段的最后16个单元中,那么它的最后一个字符的位置:F000:FFFF,是显而易见的。我们可以将ds:si指向 F000H段的最后一个单元,将es:di指向data段中的最后一个单元,然后逆向(即从高地址向低地址)传送16个字节即可。

相关信息如下:

  • ① 传送的原始位置:F000:FFFF;
  • ② 传送的目的位置:data:000F;
  • ③ 传送的长度:16;
  • ④ 传送的方向:因为逆向传送(每次串传送指令执行后,si 和 di 递减)比较方便,所以设置 DF=1。

编写程序:

代码语言:javascript
代码运行次数:0
复制
mov ax,0f000h
mov ds,ax
mov si,0ffffh 		;ds:si指向f000:ffff
mov ax,data
mov es,ax
mov di,15     		;es:di指向data:000F
mov cx,16   		;(cx)=16,rep循环16次
		
std               	;设置DF=1,逆向传送
rep movsb

2. pushf 和 popf

pushf:将标志寄存器的值压栈;

popf:从栈中弹出数据,送入标志寄存器中。

pushf 和 popf,为直接访问标志寄存器提供了一种方法。

3. 标志寄存器在 Debug 中的表示

在Debug中,标志寄存器是按照有意义的各个标志位单独表示的。在Debug中,我们可以看到下面的信息。

下面列出 Debug 对我们已知的标志位的表示。

结语

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. DF 标志和串传送指令
    • 1.1 DF 标志
    • 1.2 串传送指令
      • 1.2.1 字节串传送
      • 1.2.2 字串传送
    • 1.3 与rep配合使用的串传送
      • 1.3.1 rep movsb
      • 1.3.2 rep movsw
    • 1.4 设置DF位
    • 1.5 例题演示与巩固
      • 1.5.1 问题一
      • 1.5.2 问题一的分析与程序实现
      • 1.5.3 问题二
      • 1.5.4 问题二的分析与程序实现
  • 2. pushf 和 popf
  • 3. 标志寄存器在 Debug 中的表示
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档