汇编语言关于程序的模块化编写

模块化程序设计

mul乘法指令

  • 要么都是8位,要么都是16位
  • 8位:一个数放在AL中,另一个数放在8位reg寄存器或内存单元中
  • 16位:一个数放在AX中,另一个数放在16位reg寄存器或内存单元中
  • 结果:8位乘法:放在AX中;16位乘法:低位放在AX中,高位放在DX中

8位乘8位:

assume cs:code
code segment
start: mov al,100
mov bl,10
mul bl
code ends
end start

100和10 都是8位(小于256),所以一个数放在al中,另一个数放在另一个8位reg寄存器中,结果放在ax中。 执行结果:ax=03e8h

16位乘16位:

assume cs:code
code segment
start: mov ax,100
mov bx,10000
mul bl
code ends
end start

由于bx为16位,所以另一个数一定为16位,16位对16位,ax存放一个树,16位reg寄存器存放另一个数。结果结果:ax=4240(低16位) dx=0001(高16位)

模块化程序设计

三个示例来解决模块化程序设计需要注意的三个问题

参数传递的问题

示例:使用子程序的思想,计算N的3次方

可以使用mul指令,进行三次ax与reg寄存器相乘。将结果存放在dx或ax中

; 计算N的3次方
assume cs:code
data segment
dw 1,2,3,4,5,6,7,8 ;存放原始数据
dd 0,0,0,0,0,0,0,0 ;存放相乘结果
data ends
code segment
start: mov ax,data
mov ds,ax
mov di,0 ;原始数据的起始地址
mov si,16 ;结果存储的起始地址
mov cx,8
s: mov bx,[di]
call go
;返回到这里
mov [si],ax ;ax存放低16位
mov [si+2],dx ;dx存放高16位
add di,2 ;数据移动
add si,4 ;目标位置移动
loop s
;结束程序
mov ax,4c00h
int 21h
go: mov ax,bx
mul bx
mul bx
ret ;返回主程序
code ends
end start

分别计算每一个数字的3次方,将结果存储到dd的双字型内存单元中,从主程序传递ds数据到子程序,计算后返回结果送到目的地,同时注意原始数据和目标数据的偏移地址的移动

批量数据传递

示例:将一个字符串全部转换为大写

批量的将字符串长度和地址传递给子程序,进行转换后再回到主程序

提示:

  • 将小写字母转换为大写字母: 与运算: and al,11011111B
  • 将大写字母转换为小写字母: 或运算: or al,00100000B
;转大写
assume cs:code
data segment
db 'woshixiaoxiehhhh'
data ends
code segment
start: mov ax,data
mov ds,ax
mov bx,0
mov si,0 ;字符串的偏移地址
mov cx,16 ;字符串长度
call go
;程序结束
mov ax,4c00h
int 21h
go: and byte ptr [si],11011111B ;指明接受的是byte型字节数据
inc si ;偏移地址移动定位每个字符
loop go ;循环处理每个字符
ret ;返回主程序
code ends
end s

传递给子程序长度,即cx,来在子程序中对每个字母进行与运算,处理完毕后在统一回到主程序

寄存器冲突问题

示例:将多个字符串转换为大写

和上一题基本一致,但是要处理多行,用一个si或者di记录位置,这样能解决吗?

提示:没必要传给子程序cx来记录字符串的长度,直接用jcxz(如果cx为0,则执行跳转)来检测结束

;jcxz检测零实现
assume cs:code
data segment
db 'woshixiaoxie',0,0,0,0
db 'woshixiaoxie',0,0,0,0
db 'woshixiaoxie',0,0,0,0
db 'woshixiaoxie',0,0,0,0
db 'woshixiaoxie',0,0,0,0
data ends
code segment
start: mov ax,data
mov ds,ax
mov bx,0
mov cx,5
s1: mov si,bx ;字符串的偏移地址
push cx ;临时保存主程序CX
call go
;CX出栈,保持主程序和子程序的cx不一样
pop cx ;临时保存cx
add bx,16 ;换行
loop s1 ;循环
mov ax,4c00h
int 21h
go: mov cl,[si]
mov ch,0 ;判断cx是否为零
jcxz over ;使用jcxz则无需直到字符串的长度,只要cx为零,则终止
and byte ptr [si],11011111B
inc si ;偏移地址移动定位每个字符
loop go ;循环处理每个字符
over: ret ;返回主程序
code ends
end start

注意:此题用jcxz over表示遇到零则结束,在子程序中将按照ds数据段的数据来判断CX,进而判断字符除按是否到达末尾,最后利用jcxz返回主程序。注意!!!!!!
在返回主程序后!!子程序的cx也会返回,进而覆盖了主程序的cx(原本外层的cx用来换行每一个字符串),因此需要利用在进入子程序之前或者进入子程序马上push cx来保存外层的cx,在结束到over或者处理结束进入主程序之后再pop cx得到原来外层的cx,进而进行下一行字符串的处理

posted @   hugeYlh  阅读(34)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示