《汇编语言》王爽(第四版) 第十一章 实验11

文章目录

前言

一、实验任务

二、实现思路

三、实现代码

四、DIY时间

1.需求分析

2.最终效果

3.实现代码

总结


前言

本文是王爽老师《汇编语言》(第四版) 第十一章 实验11 的分析及代码,并在此基础上做了小小的优化,方便直观地进行程序测试。

一、实验任务

编写一个子程序,将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母。

名称:lectterc  

功能:将以0为结尾的字符串中的小写字母转变成大写字母

参数:ds:si指向字符串首地址

assume cs:code,ds:data
data segment
    db 'welcome to masm!haha,I am happy!',0
data ends

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

    mov ax,4c00H            
    int 21H

letterc:


code ends
end start

   

二、实现思路

用循环遍历每一个字符字节,检测是否为小写字母。根据书上给出的例子的思路,先判断 “若不是”,则直接跳转下一个;再判断 “若是”,则转为大写字母,然后跳转下一个。遇到0则结束循环,程序返回。

三、实现代码

assume cs:code,ds:data
data segment
    db 'welcome to masm!haha,I am happy!',0
data ends

code segment
start:
    mov ax,data             ;设置ds:si指向data段字符串首地址
    mov ds,ax
    mov si,0
    call letterc

    mov ax,4c00H            ;程序返回
    int 21H

;函数:将字符串转为大写
letterc:
    ;功能:将指定位置、任意长度、以0结尾的字符串中
    ;       所有小写字母转为大写字母
    ;参数:ds:si指向字符串首地址
    ;返回:无
 
    ;实现思路:用循环遍历每一个字符字节,检测是否为
    ;小写字母,若是,则转为大写字母,否则下一个。
    ;遇到0则结束循环,程序返回。
 
    push cx         ;将用到的寄存器压入栈
    push si
 
    mov cx,0        ;初始化
    s:              ;循环体
    mov cl,ds:[si]  ;取当前字符字节
    jcxz ok      ;若当前字节为0,则结束循环,跳转
    cmp cx,61H  ;与字符'a'比较
    jb next     ;若<字符'a'则跳转
    cmp cx,7AH  ;与字符'z'比较
    ja next     ;若>字符'z'则跳转
    sub cx,20H  ;执行这句的,就是小写字母,则转大写
    mov ds:[si],cl  ;将大写字母存到内存中
    jmp next    ;转换后也跳转到下一个
 
    next:       ;取下一个字符
    inc si
    loop s      ;重新执行循环

    ok:         ;程序返回
    pop si      ;在返回前将寄存器的值pop出来
    pop cx

    ret       

code ends
end start

   

四、DIY时间

1.需求分析

这一章的实验出奇地简单,微微有些不适应。于是决定自己动手增加一些功能,也当作对之前知识的复习。

这个实验,每次测试,都需要手动查看相关内存地址中的数据,才能判断程序是否运行正确。这有点麻烦。既然已经学过了向显存中复制数据的知识,那么我决定将转换前与转换后的字符串都显示在屏幕上,这样,转换是否正确就一目了然!

这里需要用到的子程序功能,就是将指定字符串显示在屏幕指定位置。这个子程序在之前的实验中已经写过,但是这里使用这一章学习的movsb传送指令,修改一下原先的代码,再重新写一次。正好也可以复习之前的知识。

这样,在主程序中,只要在调用 letterc子程序的前后各调用一次用于显示字符串的程序(注意要指定不同的显示行号),就能在屏幕上分别显示出转换前后的字符串了。

2.最终效果

显示效果如下。

运行结果

3.实现代码

完整的代码如下。

assume cs:code,ds:data
data segment
    db 'welcome to masm! haha,I am happy!',0
data ends
 
stack segment
    db 0
stack ends
 
code segment
start:
    ;设置段地址
    mov ax,data     ;设置ds指向data段
    mov ds,ax
    mov ax,stack    ;设置ss指向stack段
    mov ss,ax
    mov sp,10H
    
    ;显示原始字符串
    mov dh,08H      ;指定屏幕显示的行号
    mov dl,3H       ;指定屏幕显示的列号
    mov bl,0CH       ;指定屏幕显示的字符属性
    call show_str   ;将转换前的字符串显示在屏幕上
    
    ;进行大小写转换
    mov si,0        ;ds:si指向data段字符串首地址
    call letterc    ;将小写字母转为大写字母
 
    ;显示转为大写后的字符串
    mov dh,0DH      ;指定屏幕显示的行号
    mov dl,3H       ;指定屏幕显示的列号
    mov bl,2H       ;指定屏幕显示的字符属性
    call show_str   ;将转换后的字符串显示在屏幕上
 
    mov ax,4c00H            ;程序返回
    int 21H

;函数:显示字符串
show_str:
    ;功能:将指定位置、任意长度、以0结尾的字符串显示
    ;   在屏幕指定位置上。
    ;参数:ds:si指向字符串首地址,dh是指定行号,dl是指定列号,
    ;   bl是指定属性字节
    ;返回:无
    
    ;实现思路:利用movsb传送指令,将指定字符串传送到显存地址中
 
    push es     ;将用到的寄存器压入栈暂存
    push di
    push si 
    push ax
    push dx
    push cx
 
    mov ax,0B800H   ;设置es指向显存区域段地址
    mov es,ax
 
    mov ax,0A0H     ;计算显存中首字符的偏移地址
    mul dh
    mov dh,0
    add ax,dx       ;一个字符占2个字节,所以要加上 2*dl
    add ax,dx
    mov di,ax       ;将显存中首字符偏移地址赋值给di
 
    mov cx,0        ;初始化
    cld             ;设置DF标志位为0,传送正向进行
    show_next:      ;逐个字符进行显示
    mov cl,ds:[si]    ;取一个字符字节
    jcxz show_ok    ;若当前字节为0,则跳转
    movsb           ;从ds:[si]向es:[di]传送一个字节,之后自动si+1,di+1
    mov es:[di],bl  ;将属性字节复制到显存中
    inc di
    jmp show_next
 
    show_ok:        ;程序返回
    pop cx          ;将寄存器的值pop出来
    pop dx
    pop ax
    pop si
    pop di
    pop es
 
    ret
 
;函数:将字符串转为大写
letterc:
    ;功能:将指定位置、任意长度、以0结尾的字符串中
    ;       所有小写字母转为大写字母
    ;参数:ds:si指向字符串首地址
    ;返回:无
 
    ;实现思路:用循环遍历每一个字符字节,检测是否为
    ;小写字母,若是,则转为大写字母,否则下一个。
    ;遇到0则结束循环,程序返回。
 
    push cx         ;将用到的寄存器压入栈
    push si
 
    mov cx,0        ;初始化
    s:              ;循环体
    mov cl,ds:[si]  ;取当前字符字节
    jcxz ok      ;若当前字节为0,则结束循环,跳转
    cmp cx,61H  ;与字符'a'比较
    jb next     ;若<字符'a'则跳转
    cmp cx,7AH  ;与字符'z'比较
    ja next     ;若>字符'z'则跳转
    sub cx,20H  ;执行这句的,就是小写字母,则转大写
    mov ds:[si],cl  ;将大写字母存到内存中
    jmp next    ;转换后也跳转到下一个
 
    next:       ;取下一个字符
    inc si
    loop s      ;重新执行循环

    ok:         ;程序返回
    pop si      ;在返回前将寄存器的值pop出来
    pop cx

    ret     
 
code ends
end start
 

总结

本文是王爽老师《汇编语言》(第四版) 第十一章 实验10 的分析及代码,并在此基础上做了小小的优化。通过这个实验,主要复习了cmp指令以及对应的条件转移指令,顺道复习了向显存中写入数据的方法以及movsb传送指令。

  • 10
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值