王爽 汇编语言个人疑问汇总第九篇
第11章
实验11 编写子程序
-
编写一个子程序,将包含任一字符,以0结尾的字符串中的小写字母转变成大写字母。
-
描述如下:
名称:letterc
功能:将以-结尾的字符串中的小写字母转变成大写字母
参数:ds:si指向字符串首地址
程序分析
- 要把字符串中的小写字母转化为大写字母,就要把字符串中的小写字母识别出来,在ASCII码中小写字母区间是
[61h,7ah]
,所以只要满足低于61h高于7ah的字符就是大写字母
。
完整代码
assume cs:code
data segment
db "Beginner's All-purpose Symbolic Instruction Code.",0
data ends
code segment
begin:
mov ax,data
mov ds,ax
mov si,0
call letterc ;调用子程序
mov ax,4c00h
int 21h
letterc:
push cx ; 保护现场
pushf ; 保护现场
mov cx,0 ; cx 设置为0
s1:
mov cl,ds:[si]
jcxz ok_ret ; 如果取到最后一个字节0 , 就跳转到ok_ret代码段
cmp cl,61h
jb nextgo ;低于61h转移
cmp cl,7ah
ja nextgo ;高于7ah转移
and cl,0dfh ;转化为大写,二进制是11011111 ,大写第5位是0,“与” 都为1时就是1,这里“与”第5为都会是0,转为大写
mov ds:[si],cl
nextgo:
inc si ; 下一个字节
jmp short s1 ; 跳转到s1代码段
ok_ret:
popf ; 还原现场
pop cx ; 还原现场
ret ;返回
code ends
end begin
- 因为这个没有显示出来不能直观看到结果,下面加个打印,其实是加了王爽 汇编语言个人疑问汇总第七篇的打印代码。完整代码如下。
assume cs:code
data segment
db "Beginner's All-purpose Symbolic Instruction Code.",0
data ends
code segment
begin:
mov ax,data
mov ds,ax
mov si,0
call letterc ;调用子程序
;------------------打印字符串 start----------------------
mov dh,8 ; 第8行
mov dl,3 ; 第3列
mov cl,2 ; 颜色 2 的二进制是10,
; 参考书上实验9 根据材料编程对颜色的说明可得知
; 此处表示绿色
mov ax,data ; 代码段data指向ax寄存器
mov ds,ax ; (ds) = (ax)
mov si,0 ; 字符串的首地址
call show_str ; 调用子程序
;------------------打印字符串 end----------------------
mov ax,4c00h
int 21h
letterc:
push cx ; 保护现场
pushf ; 保护现场
mov cx,0 ; cx 设置为0
s1:
mov cl,ds:[si]
jcxz ok_ret ; 如果取到最后一个字节0 , 就跳转到ok_ret代码段
cmp cl,61h
jb nextgo ;低于61h转移
cmp cl,7ah
ja nextgo ;高于7ah转移
and cl,0dfh ;转化为大写,二进制是11011111 ,大写第5位是0,“与” 都为1时就是1,这里“与”第5为都会是0,转为大写
mov ds:[si],cl
nextgo:
inc si ; 下一个字节
jmp short s1 ; 跳转到s1代码段
ok_ret:
popf ; 还原现场
pop cx ; 还原现场
ret ;返回
;-----------------------------打印字符串 start----------------------
show_str: ;其实这是一个子程序,里面是包含s和ok的,这样理解容易些
push ax
push bx
push dx
push cx
push es
push si ; 保存程序中用到的相关寄存器,对于这个程序中其实并没有使用到从栈中取出的寄存器数据,
; 个人觉得可能是一种编码习惯吧,放到栈中保护现场,以便后续的功能用到
mov al,160 ; 每行80个字符,所以每行占160个字节(参考参考书上实验9 根据材料编程对颜色的说明可得知), 160 和 下面dh的值都小于255,做8位乘法
mul dh ; (dh) = 8
mov bx,ax ; 160 * dh 运算结果在ax中 , 再赋值给bx ,计算的行的偏移量
mov al,2 ; 计算列的偏移量,每列占2个字节
mul dl ; (dl) = 2
add bx,ax ;计算出行和列加起来的偏移量,放在bx里
sub bx,2 ; 列号从0开始,最终结果要-2 才会显示在第3列
mov ax,0B800h ; 显示缓冲区固定地址
mov es,ax ;通过段寄存器es来操控要显示的内容,es:[bx]为要输入的显示区
mov al,cl ;先将cl中的颜色放在al
mov ch,0 ;cx高位ch为0,因为用不上
s:
mov cl,[si] ; 把代码段中的数据赋值给cx寄存器低位cl
jcxz ok ; 利用jcxz指令特性,cx=0时就会调用ok代码段,程序调用ok代码段,最后返回。
mov es:[bx],cl ; 低位存字符
mov es:[bx+1],al ; 高位存颜色
add bx,2 ; 往前偏移2个字节(1个字节存字符,1个字节存颜色),准备存下一个字符
inc si ; 下一个字符的偏移量
jmp short s ; 跳转到s代码段第一行指令
ok: ;返回
pop si ; 把前面放入栈中的寄存器,依次取出来,相当于还原了
pop es
pop cx
pop dx
pop bx
pop ax
ret
;-----------------------------打印字符串 end----------------------
code ends
end begin
- 结果
本题参考
- https://blog.csdn.net/weixin_42553435/article/details/81157700
- https://www.cnblogs.com/tsembrace/p/3267166.html
第12章
检测点12.1
(1)
- 用Debug查看内存,情况如下:
0000:0000 68 10 A7 00 8B 01 70 00-16 00 9D 03 8B 01 70 00
分析
- 一个表项占两个字,也就是4个字节。高地址存放段地址,低地址存放偏移地址。
- 对于
68 10 A7 00
是0号中断处理入口地址,也就是007A:1068。然后依次往下数。
答案
- 则3号中断源对应的中断处理程序的入口地址为:
0070:018B
(2)
- 存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:
4*N
。 - 存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:
4*N+2
。