本文主要是介绍(十)《汇编语言(王爽)》 | 实验 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
、.
、
、f
、i
、l
、e
的 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:实践课程中的程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!