(十)《汇编语言(王爽)》 | 实验 6:实践课程中的程序

2024-01-05 18:08

本文主要是介绍(十)《汇编语言(王爽)》 | 实验 6:实践课程中的程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 预备知识

  • 目前为止还没有涉及到判断语句的使用,可通过大小写字符的二进制形式来进行大小写转换:
A 41 0100 0001    B 42 0100 0010    C 43 0100 0011  ...
a 61 0110 0001    b 62 0110 0010    c 63 0110 0011  ...

可观察到,对应大小写字符仅有第 5 位不同,所以可通过汇编指令按位与指令 and 和按位或指令 or 完成字符的大小写转换。如将字符转换为大写字符:and 1101 1111,将字符转换为小写字符:or 0010 0000。

  • SI 和 DI 是 8086CPU 中和 BX 功能相近的寄存器,但 SI 和 DI 不能分为两个 8 位寄存器
  • 根据不同场景使用不同寻址方式:
  • [idata] 用一个常量表示地址,可用于直接定位一个内存单元
  • [bx] 用一个变量表示地址,可用于间接定位一个内存单元
  • [bx+idata] 用一个常量和变量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
  • [bx+si] 用两个变量表示地址
  • [bx+si+idata] 用两个变量和一个常量表示地址
  • 前面提到,寄存器 CX 用以配置 loop 指令实现循环,如果涉及到多重循环,则内层循环的 CX 值会影响外层循环的值,解决办法是使用栈来暂存数据

2. 实验任务

(1)将 datasg 段中每个单词的头一个字母改为大写字母。

assume cs:codesg,ds:datasg
datasg segmentdb '1. file         'db '2. edit         'db '3. search       'db '4. view         'db '5. options      'db '6. help         '
datasg ends
codesg segment
start:?		;待完成部分
codesg ends
end start

在定义数据段时,字符串后半部分使用空格填充至 16 字节,其在内存中的存放形式为:

在这里插入图片描述
可以看到,每个单词的第一个字母的相对位置都相同,即第 3 列。所以,可以使用一重循环完成,循环每次索引上二维数组的行,然后每次定位到行的第 3 列即可索引到相应字母,最后使用逻辑与运算将字符转换为大写字母。

	mov ax,datasgmov ds,ax			;使用段寄存器DS指向数据段datasgmov bx,0			mov cx,6			;循环次数
s:	mov al,[bx+3]		;将相对于BX偏移3个位置的字符送入寄存器AL中and al,11011111b	;通过逻辑与运算将字母转换为大写字母mov [bx+3],al		;将转换后的字符重写回对应的内存单元add bx,16			;BX每次偏移16个位置loop smov ax,4c00hint 21h

使用指令 g 跳到循环执行前,此时寄存器 DS 为字符串存放内存的段地址:

请添加图片描述

以 076A:0000~076A:000F 为例,里面存放了第一个字符串的内容,21、2E、20、66、69、6C、65 分别为字符 1. file 的 ASCII 码值,后面连续的 20 为填充的空格。待改变部分的偏移地址为 3,即 66、65、73、76、6F 和 68。程序执行结束后再查看这段内存单元:

请添加图片描述

(2)将 datasg 段中每个单词的字母改为大写字母。

assume cs:codesg,ds:datasg
datasg segmentdb 'ibm             'db 'dec             'db 'dos             'db 'vax             '
datasg ends
codesg segment
start:?		;待完成部分
codesg ends
end start

在定义数据段时,字符串后半部分使用空格填充至 16 字节,其在内存中的存放形式为:

在这里插入图片描述
和上一题只改变一个字母不同,本题要求同时改变三个字母,所以使用双重循环完成。同样地,外层循环用于索引每个字符串,内层循环遍历字符串中的每个字符。注意,上面提到多重循环需要注意循环控制量 CX 的存取,这里使用栈

stacksg segment			;额外定义栈段用于存取寄存器CX的值dw 0,0,0,0,0,0,0,0
stacksg endsmov ax,stacksgmov ss,axmov sp,16		;定义空栈mov ax,datasgmov ds,axmov bx,0		;使用段寄存器DS指向数据段datasgmov cx,4		;外层循环次数
s1:	push cx	;使用栈保存CX的值mov si,0		;内层循环的偏移mov cx,3		;内层循环次数
s2:	mov al,[bx+si]	;内层循环完成将字母转换为大写字母and al,11011111bmov [bx+si],alinc si			;内层每次偏移1个字节loop s2add bx,16		;外层循环每次偏移16个字节pop cx			;恢复CX的值loop s1mov ax,4c00hint 21h

(3)将 datasg 段中每个单词的前四个字母改为大写字母。

assume cs:codesg,ds:datasg
datasg segmentdb '1. display      'db '2. brows        'db '3. replace      'db '4. modify       '
datasg ends
codesg segment
start:?		;待完成部分
codesg ends
end start

在定义数据段时,字符串后半部分使用空格填充至 16 字节,其在内存中的存放形式为:

在这里插入图片描述

本题和上一题思路类似,外层循环功能完全一致,内存循环也是实现功能将固定数量的字母转换为大写。在上一题中,每行待改变字母的起始偏移为 0,本题为 3;所以,上一题使用 [bx+si] 来定位起始字母,本题使用 [bx+si+3] 来定位起始字母。

stacksg segment			;额外定义栈段用于存取寄存器CX的值dw 0,0,0,0,0,0,0,0
stacksg endsmov ax,stacksgmov ss,axmov sp,16		;定义空栈mov ax,datasgmov ds,axmov bx,0			;使用段寄存器DS指向数据段datasgmov cx,4			;外层循环次数
s1:	push cx				;使用栈保存CX的值mov si,0			;内层循环的偏移mov cx,4			;内层循环次数
s2:	mov al,[bx+si+3]	;内层循环完成将字母转换为大写字母and al,11011111bmov [bx+si+3],alinc si				;内层每次偏移1个字节loop s2add ax,16			;外层循环每次偏移16个字节pop cx				;恢复CX的值loop s1mov ax,4c00hint 21h

如果需要将前 5 个字母转换为大写,则 8 位寄存器 AL 的存储空间不足。

这篇关于(十)《汇编语言(王爽)》 | 实验 6:实践课程中的程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573709

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

Spring Boot统一异常拦截实践指南(最新推荐)

《SpringBoot统一异常拦截实践指南(最新推荐)》本文介绍了SpringBoot中统一异常处理的重要性及实现方案,包括使用`@ControllerAdvice`和`@ExceptionHand... 目录Spring Boot统一异常拦截实践指南一、为什么需要统一异常处理二、核心实现方案1. 基础组件

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬