【新书推荐】17.3 字符串操作举例

本节内容:字符串操作举例。

         ■例3:接收字符串去掉空格后逆向输出,t17-3.asm。

         ■例4:字符串拼接,t17-4.asm。

         ■例5:判断子串,t17-5.asm。

17.3.1 例3:接收字符串去掉空格后逆向输出

动手实验105写一个程序,先接收一个字符串,然后抽去其中的空格,最后按相反的顺序显示。

在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。

算法分析:

第一步:DOS 10号功能接收字符串;

第二步:repz scasb过滤空格;

第三步:先入栈后出栈的方式逆向输出。

■流程图如图17-1所示。

图17-1 接收字符串去掉空格后逆向输出

示例代码81

;例3:写一个程序,先接收一个字符串,然后抽去其中的空格,最后按相反的顺序显示

;请注意删除空格的方法和方向标志的变化

;程序名:t17-3.asm

;功能:接收一个字符串,去掉其中的空格后按相反的顺序显示

;=========================================================

;符号常量的定义

maxlen=16       ;字符串最大长度

space=' '           ;空格

cr=0dh               ;回车符

lf=0ah                ;换行符

;数据段的定义

assume cs:code,ds:data

data segment

buffer db maxlen+1,0,maxlen+1 dup(0)

string db maxlen+3 dup(0)

data ends

code segment

start:

         mov ax,data

         mov ds,ax

         mov es,ax

         ;

         mov dx,offset buffer

         mov ah,10

         int 21h

         ;

         mov cl,buffer+1

         xor ch,ch

         jcxz ok

         ;

         cld

         mov si,offset buffer+2

         mov di,offset string

         ;预处结尾字符0

         mov al,0

         stosb        

         ;过滤空格

         mov al,space

pp1:

         jcxz pp3

         xchg si,di  ;si=string,di=buffer

         repz scasb

         xchg si,di  ;si=buffer,di=string

         dec si        ;scasb回退

         inc cx        ;repz回退

         ;

pp2:

         cmp byte ptr[si],space;si=buffer,di=string

         jz pp1

         movsb

         loop pp2

pp3: ;string存入回车换行              

         mov al,cr

         stosb

         mov al,lf

         mov [di],al       

         ;倒序显示                                                               

         std

         mov si,di

pp4:

         lodsb

         or al,al

         jz ok                                                                 

         mov dl,al

         mov ah,2

         int 21h

         jmp pp4

ok:

         mov ax,4c00h                                                         

         int 21h

code ends

end start

请注意上述示例中方向标志位的处理,以及删除空格字符的处理方法。

17.3.2 例4:字符串拼接

动手实验106写一个在字符串1后追加字符串2的程序,设字符串均以0结尾。

在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。

算法分析:

第一步:将变址DI指针移到字符串1结尾;

第二步:计算字符串2的长度;

第三步:repz movsw指令将字符串2复制到字符串1结尾处;

注意奇数字节的处理movsb。

示例代码82

;例4:写一个在字符串1后追加字符串2的程序,设字符串均以0结尾

;程序名:t17-4.asm

;功能:字符串1后追加字符串2

;=========================================================

assume cs:code,ds:data

;符号常量的定义

maxlen=16       ;字符串最大长度

data segment

buffer1 db "1234",maxlen dup(0)

buffer2 db "56789",24h,0

data ends

code segment

start:

         mov ax,data

         mov ds,ax

         ;

         mov si,offset buffer1

         mov di,offset buffer2

         call strcat

         ;       

         mov dx,offset buffer1

         mov ah,9

         int 21h

         ;

         mov ax,4c00h

         int 21h

;-----------------------------------------------------

;写一个在字符串1后追加字符串2的子程序,设字符串均以0结尾

;说明:传送的字符串2包括结束标志,

;并从偶地址开始字传送(偶地址效率高,也可以直接传送),需要考虑可能遗留一个字节

;子程序名:strcat

;功能:在字符串1末尾追加字符串2

;入口参数:DS:SI=字符串1起始地址的段值:偏移

;DS:DI=字符串2起始地址的段值:偏移

;出口参数:无

;说明,不考虑字符串1后是否留有足够的空间

strcat proc

         push es

         push ax

         push cx

         push si

         push di

         cld

         push ds

         pop es                ;使ES同DS

         ;将si指针移到字符串1的结尾0处

         push di

         mov di,si            ;将字符串1作为目的串

         xor al,al

         mov cx,0ffffh

         repnz scasb      ;确定字符串1的尾 zf=1时

         lea si,[di-1]        ;si指向字符串1的结束标志

;测量字符串2的长度

         pop di

         mov cx,0ffffh

         repnz scasb      ;测量字符串2的长度

         not cx                ;CX包括结束标志字符串2的长度

         sub di,cx            ;DI再次指向字符串2的首

         ;将字符串2添加到字符串1结尾处

         xchg si,di           ;为拼接做准备

strcat1:

         shr cx,1           ;移动数据库长度除2

         repz movsw      ;字移动、ZF=0时结束

         jnc strcat2        ;进位标志CF=0

         movsb                ;补字移动遗留的一字节

strcat2:    ;

         pop di

         pop si

         pop cx

         pop ax

         pop es

         ret   

strcat endp

code ends

end start

上述示例先将指针移到字符串1的结尾处,然后将字符串2拷贝到字符串1的结尾处。注意,此代码实现为了提高拷贝效率,使用MOVSW指令,但需要考虑奇数个字节,最后一个奇数字节使用MOVSB指令。该示例对这一细节的处理有所冗余,请读者尝试优化代码。

17.3.3 例5:判断子串

动手实验107写一个判字符串2是否为字符串1的子串的程序,设字符串均以0结尾。

在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。

算法分析:

第一步:分别测量字符串1和字符串2的长度;

第二步:双循环结构匹配字符串2和字符串1;

第三步:输出结果;

伪代码:参见示例代码47

流程图:如图17-2所示。

示例代码83

;例5:写一个判字符串2是否为字符串1的子串的程序,设字符串均以0结尾

;程序名:t17-5.asm

;功能:判字符串2是否为字符串1的子串

;=========================================================

assume cs:code,ds:data

data segment

string1 db "12345",0

string2 db "1234",0

result1  db "YES!",24H

result2  db "NO!",24H

data ends

code segment

start:

         mov ax,data

         mov ds,ax

         mov es,ax

         ;判断子串

         mov si,offset string1

         push ds

         push si

         mov di,offset string2

         push es

         push di

         call far ptr strstr

         ;输出结果

         or ax,ax

         jz NO

         mov dx,offset result1

         mov ah,9

         int 21h

         jmp OVER

NO: 

         mov dx,offset result2

         mov ah,9

         int 21h

         ;

OVER:

         mov ax,4c00h

         int 21h

;-----------------------------------------------------

;子程序名:strstr

;功能:判字符串2是否为字符串1的子串

;入口参数:指向字符串的远指针

;出口参数:DX:AX返回指向字符串2在字符串1中首次出现处的指针,AX=0不是子串

;说明:调用方法:

;压入字符串2的远指针

;压入字符串1的远指针

;call far ptr strstr

strstr proc far

         push bp

         mov bp,sp

         push ds

         push es

         push bx

         push cx

         push si

         push di

        

         les bx,[bp+6]                       ;取str2指针

         cmp byte ptr es:[bx],0      ;判断str2是否为空串

         jnz strstr1                  ;否

         jmp short strstr3

strstr1:

         cld

         les di,[bp+10]   ;取str1指针

         push es

         mov bx,di          ;str1偏移送bx寄存器

         xor ax,ax

         mov cx,0ffffh    ;测str1长度

         repnz scasb

         not cx

         mov dx,cx         ;dx=str1的长度(含结束标志)

        

         les di,[bp+6]     ;取str2指针

         push ds

         mov bp,di          ;str2偏移送bp寄存器

         xor ax,ax

         mov cx,0ffffh

         repnz scasb     ;测str2的长度

         not cx

         dec cx                ;cx=str2的长度(不含结尾0)

         pop ds                ;此时DS:BP指向str2

         pop es                ;ES:BX指向str1

        

         mov si,bp          ;DS:SI指向str2

         mov di,bx          ;ES:DI指向str1

         mov ax,cx         ;保存字符串2的长度

        

strstr2:

         mov cx,ax         ;cx=str2的长度(不含结尾0)

         mov di,bx          ;ES:DI指向str1

         repz cmpsb       ;在str1中搜索str2的字符  

         jcxz strstr4        ;是子串

         cmp byte ptr es:[di],0       ;str1结尾

         jz strstr3

         mov si,bp          ;不相同,DS:SI重新指向str2

         inc bx                 ;继续比对下一个字符

         jmp strstr2      

        

strstr3:

         xor ax,ax  ;不是子串

         jmp strstr5

strstr4:    

         mov ax,1

        

strstr5:

         pop di

         pop si

         pop cx

         pop bx

         pop es

         pop ds

         pop bp

         ret            

strstr endp

code ends

end start

         上述示例采用双循环结构,string2作为子串与string1进行比较。内循环将string2的每个字符与string1指定位置处的字符进行逐一比对。外循环从string1每个字符位置开始逐一与string2进行比对。

练习

1、请说明flag寄存器标志位DF的作用。如何设置DF?

2、 请写出与“LODSB”指令等价的程组合指令。

3、请写出与“STSOW”指令等价的组合指令。

4、请写出与“SCASB”指令等价的组合指令。

5、请写一个程序片段代替指令“REP MOVSW”。

6、请写一个片段代替指令“REPNZ CMPSB”。

7、请在debug调试器中观察重复前缀REP与重复前缀REPZ/REPE的机器码。

8、编写一个实现复制数据块的近过程。

9、编写一个实现字符串拷贝的近过程。堆栈传递作为参数的源和目标字符串首地址的偏移。

10、编写一个把字符串中的小写字母转换为大写(字符串以0结尾)的远过程。

11、改写例1和例2,通过堆栈传递入口参数。

12、编写一个把字符串2插入字符串1指定位置的远过程。

13、编写一个截取字符串某子串的近过程。

14、编写一个去掉字符串前导空格的近过程。

15、利用字符串操作指令写一个清屏的过程。只考虑字符显示方式。

本文摘自编程达人系列教材《X86汇编语言基础教程》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/733348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何关闭 Visual Studio 双击高亮

[问题描述]: 最近 Visual Studio 更新后,双击选中关键字快要亮瞎我的眼睛了 👀👀 [解决方法]: 摸索了一下,找到了关闭的方法:工具 → 选项 → 文本编辑器 → 常规,然后取消 勾选 sel…

蓝桥杯-串的处理,幸运数字

参照大佬写法: #include<iostream> #include<cstring> using namespace std; int main(){string str;getline(cin,str);//可以将带有空格的string输入for(int i0;i<str.size();i){if(i0&&str[i]>a&&str[i]<z) str[i]-32;//单词首字母小…

如何使用LEAKEY轻松检测和验证目标服务泄露的敏感凭证

关于LEAKEY LEAKEY是一款功能强大的Bash脚本&#xff0c;该脚本能够检测和验证目标服务中意外泄露的敏感凭证&#xff0c;以帮助广大研究人员检测目标服务的数据安全状况。值得一提的是&#xff0c;LEAKEY支持高度自定义开发&#xff0c;能够轻松添加要检测的新服务。 LEAKEY主…

【unity小技巧】Unity人物衣服布料系统的探究 —— Cloth组件

文章目录 一、Cloth组件解释基本介绍出于性能的考虑, 可以对Cloth产生影响的Collider只有两种打开编辑模式绘制 二、基本使用1. 创建出一个空物体2. 在空物体上添加cloth组件&#xff0c;可以直接点击Add Component搜索cloth添加&#xff0c;也可以在工具栏 Component–>phy…

Android UI自动化测试框架—SoloPi简介

1、UI自动化测试简介 软件测试简介 ​软件测试是伴随着软件开发一同诞生的&#xff0c;随着软件规模大型化&#xff0c;结构复杂化&#xff0c;软件测试也从最初的简单“调试”&#xff0c;发展到当今的自动化测试。 ​ 自动化测试是什么呢&#xff1f;自动化测试是把以人为…

图分割 Graph Partition 学习笔记1

文章目录 前言一、graph-partition是什么&#xff1f;二、具体分类三、graph-partition的意义参考链接 前言 最近在学习图论划分的方法&#xff0c;碰巧搜索到了这个算是对我而言全新的一个体系&#xff0c;在这里将逐步记载自己的学习资料和进度&#xff0c;希望和大家一起探讨…

HAProxy集群与常见的Web集群软件调度器对比

一.常见的Web集群调度器 Web集群调度器分为软件和硬件&#xff1a; 1.常用软件调度器&#xff1a; &#xff08;1&#xff09;LVS&#xff1a;性能最好&#xff0c;搭建复杂 &#xff08;2&#xff09;Nginx&#xff1a;性能较好&#xff0c;但集群节点健康检查功能呢不强&…

Rust教程:How to Rust-从开始之前到Hello World

本文为第0篇 专栏简介 本专栏是优质Rust技术专栏&#xff0c;推荐精通一门技术栈的蟹友&#xff0c;不建议基础的同学&#xff08;无基础学Rust也是牛人[手动捂脸]&#xff09; 感谢Rust圣经开源社区的同学&#xff0c;为后来者提供了非常优秀的Rust学习资源 本文使用&…

为什么不用 index 做 key?

“在 Vue 中&#xff0c;我们在使用 v-for 渲染列表的时候&#xff0c;为什么要绑定一个 key&#xff1f;能不能用 index 做 key&#xff1f;” 在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。 虚拟DOM 我们知道&#xff0c;Vue 不可以直接操作 DOM 结构&am…

避免重复数据产生

在MySQL表中&#xff0c;可以通过创建唯一索引或唯一约束来确保表中除了ID以外的其他字段不能有两条记录相同的值。 创建唯一索引&#xff1a; CREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...); 其中&#xff0c;index_name是索引的名称&#xff0c;ta…

AI大模型,掀起新一波智能浪潮!

AI大模型的出现&#xff0c;标志着人工智能技术迈入了一个新的阶段。这些巨大的模型不仅在规模上超越了以往任何其他人工智能系统&#xff0c;而且在性能上也取得了巨大的突破。由于其庞大的参数量和复杂的结构&#xff0c;AI大模型在各个领域展现出了强大的学习能力和推理能力…

【机器学习】在Python中进行K-Means聚类和层次聚类

Python中聚类算法API的使用指南 聚类分析是数据分析中一种常见的无监督学习方法&#xff0c;通过将相似的对象分组在一起&#xff0c;我们能够识别出数据集中的自然分群。本文将介绍如何使用Python中的聚类算法接口&#xff0c;KMeans和层次聚类方法。 K-Means 聚类 K-Means…

EdgeX Foundry - 连接 Modbus 设备

文章目录 一、概述1.安装说明2.Modbus Slave 工具 二、连接 Modbus 设备1.docker-comepse2.设备配置文件3.启动 EdgeX Foundry4.访问 UI4.1. consul4.2. EdgeX Console 5.创建 Modbus 设备5.1.创建设备配置文件5.2.添加设备 6.测试6.1.命令6.2.事件6.3.读值 EdgeX Foundry # E…

JavaEE进阶篇 (一) -- Maven

写在前&#xff1a;Hello各位小伙伴们&#xff0c;这一部分主要对JavaEE进阶部分内容进行学习记录&#xff0c;关于前面学习的内容也会同步更新~~ 在学习新内容之前&#xff0c;需要了解一下基础的内容&#xff1a; JavaEE(Java Platform Enterprise Edition),Java平台企业版&…

面试经典150题——环形链表

Suffering, for the weak is the tomb of death, and for the strong is the soil of germinal ambition.​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 这个题目就是判断一个链表有没有环&#xff0c;其实我们之讲过一个题目&#xff0c;就实现了判断链表有没有环的步骤&a…

LeetCode---387周赛

题目列表 3069. 将元素分配到两个数组中 I 3070. 元素和小于等于 k 的子矩阵的数目 3071. 在矩阵上写出字母 Y 所需的最少操作次数 3072. 将元素分配到两个数组中 II 一、将元素分配到两个数组中I 直接按照题目要求进行模拟即可&#xff0c;代码如下 class Solution { p…

探索 ON1 Resize Ai 2023.5 for Mac/win:释放图像的无限可能

ON1 Resize AI 2023.5 for Mac/Win 是一款专业的图像无损放大软件&#xff0c;通过人工智能技术&#xff0c;能够将图像放大至更高的分辨率&#xff0c;同时保持图像细节和清晰度的最佳状态。该软件的强大功能和直观的操作界面&#xff0c;使它成为摄影师、设计师和艺术家的理想…

讲解人工智能在现代科技中的应用和未来发展趋势。

目录 1.人工智能在现代科技中的应用 1.1医疗健康 1.2交通运输 1.3金融服务 1.4教育 1.5制造业 1.6客户服务 2.未来发展趋势 2.1泛化能力提升 2.2跨领域集成学习 2.3增强的可解释性和透明度 2.4AI伦理和法规 2.5量子计算与AI的结合 2.6AI与物联网&#xff08;IoT&…

滴滴一面:Keepalived+Nginx高可用,如何实现IP跳跃?(1)

尼恩说在前面 HashMap的工作原理是目前java面试问的较为常见的问题之一&#xff0c;在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、百度、网易的面试资格&#xff0c;遇到很多很重要的面试…