汇编语言_实验10:编写子程序

1. 显示字符串

名称:show_str
功能:在指定位置,指定颜色,显示一个0结尾的字符串
参数:dh=行号,dl=列号,cl=颜色
如:在8号3列显示数据段的字符串。

assume cs:code,ds:data,ss:stack
data segment
	db 'Hello world!',0
data ends

stack segment
	db 128 dup(0)
stack ends

code segment
start:
	mov ax,stack
	mov ss,ax
	mov sp,128
	
	mov ax,data
	mov ds,ax
	mov si,0
	;dh行号,dl列号,cl颜色
	mov dh,8
	mov dl,3
	mov cl,00010010B

	call show_str
	
	mov ax,4c00h
	int 21h
	
show_str:
	mov ax,0b800h
	mov es,ax	;数据目的地址
	
	;将此程序段中用到的寄存器都入栈保存
	push cx
	push si
	push di
	push es
	push dx
	;设置行号
	mov al,160
	mul dh	;ax=160*dh行号偏移ax中(8位乘法)
	
	push ax ;ax=160*dh保存
	
	mov al,2
	mul dl	;ax=2*dl
	
	pop bx	;将ax=160*dh保存放入bx中
	
	add ax,bx	;ax=160*dh+2*dl
	mov di,ax	;di为es偏移地址
	
	mov ah,cl	;颜色存放在ah中,字符存放al中。
	mov cx,0
	
change:
	mov al,ds:[si]
	mov cl,al
	jcxz ok		;用cx判断
	mov es:[di],ax
	inc si
	add di,2
	push cx
	jmp short change
ok:
	pop dx
	pop es
	pop di
	pop si
	pop cx
	
	ret
code ends
end start

在这里插入图片描述

解决除法溢出问题

Div指令会存在溢出的可能,100000/10 就会溢出,如何解决溢出呢?解决方法是用书中提供的公式:
名称:divdw
功能:进行不会产生溢出的除法运算。
参数:
Ax=dword型 低16位
Dx=dword型高16位
Cx=除数
返回:
Dx = 结果高16位存放,ax=结果低16位
Cx=余数
范围:被除数X:Ffffffff
除数N:ffff
商:高16H:ffff
低16位L:ffff
Init():取商,比如,init(38/10)=3;
Rem():取余数,rem(38/10)=8
公式:
X/N=init(H/N) * 65535 + [rem(H/N) * 65535 +L]/N

assume ds:data,cs:code,ss:stack
stack segment
	db 128 dup(0)
stack ends

data segment
	dw 8 dup(0)
data ends

code segment
start:
	;数据段存放商高16,低16,余数
	mov ax,data
	mov ds,ax
	
	;计算100 0000/10
	mov ax,4240h	;16位H
	mov dx,000fh	;16位L
	mov cx,0ah		;除数N
	call divdw
	
	mov ax,4c00h
	int 21h

;X/N=init(H/N) * 65535 + [rem(H/N) * 65535 +L]/N
divdw:	
	push ax
	
	;手下计算(H/N),让ax存放余数,dx存放商
	;这也是一个32位除法
	mov ax,dx
	mov dx,0
	div cx		;ax存放商(商的高16),dx存放余数
	
	mov ds:[0],ax	;商的高16;下一次除法,余数作为高16位,低16位还是ax
	pop ax
	div cx
	
	mov ds:[2],ax		;商的低16位
	mov ds:[4],dx		;dx为余数

	mov ax,ds:[2]
	mov dx,ds:[0]
	mov cx,ds:[4]
	
	ret
code ends
end start

在这里插入图片描述

3. 显示数值

该程序将data段中的字型数据,输出为十进制数据,如最下图所示。
分三步:
第一,逐个读取每个字符;
第二,对读取到的字符,除10取模,存放在string段中;
第三,输出string段中的数据。
程序如下(目前没有将每个子功能都封装为函数,这样不便于理解):

assume cs:code,ds:data,ss:stack

data segment
	dw 1230,12666,1321,243,86,9888
data ends

;存放dw中每个余数,从右向左存放
string segment
	db 10 dup('0'),0
string ends

stack segment
	db 128 dup(0)
stack ends

code segment
start:
		mov ax,stack
		mov ss,ax
		mov sp,128
		
		call clear_screen
			
		call init_reg
		
		call show_number

		mov ax,4c00h
		int 21h

;========================================
;名称:clear_screen
;功能:清除当前显存
;参数:无
;返回:无
;应用举例:清空屏幕
;========================================
clear_screen:
		mov bx,0b800h
		mov es,bx		;显存位置
		
		mov bx,0		;显存地址		
		mov dx,0700h	
		mov cx,2000		
clearScreen:
		mov es:[bx],dx
		add bx,2
		loop clearScreen
		ret 

;========================================
;名称:init_reg
;功能:初始化参数,指明数据源和数据的目的地址
;参数:无
;返回:无
;应用举例:清空屏幕
;========================================
init_reg:
		mov bx,data			;数据源
		mov ds,bx
		
		mov bx,string		;目的位置:来存放余数
		mov es,bx
		ret
		
;========================================
;名称:show_number
;功能:在屏幕的中间位置显示转换后的十进制数
;参数:ds=data   数据源
	  ;es=string 数据目的
;返回:无
;应用举例:如显示‘12366;========================================	
show_number:		
		mov bx,0	;bx访问data中每个地址
		mov si,9	;string中最后一个字符位置
		mov di,160*10 + 30*2  ;显示的位置
		
		mov cx,6	;控制循环次数,显示data中的数据。

showNumber:		
		push cx
		push ds
		push es
		
		mov ax,ds:[bx]
		mov dx,0
;开对对ax中字数据做除法,然后存入到string:[si]
short_div:
		mov cx,10	;被除数
		div cx		;ax存放商,dx为余数
		
		add dl,30h	;将余数加30H,转换为ascii码,存放如string中
		mov es:[si],dl
		
		mov cx,ax		;利用cx判断,ax是否为0,0则停止
		jcxz shortDivRet ;否则,将ax作为新除数,继续除
		dec si
		mov dx,0		
		jmp short_div

shortDivRet:
		pop es
		pop ds
		pop cx

;开始输出的结果string中结果
		push ds
		push es
		push cx
		push di
		push bx
		
		mov bx,string
		mov ds,bx		;ds由data,改为指向string
		
		mov bx,0b800h
		mov es,bx		;es由string,改为指向显存
		mov cx,0
show_string:
		mov cl,ds:[si]	;判断待输出的字符是否为0
		jcxz showStirngRet ;如果非0,送至es中
		mov byte ptr es:[di+0],cl
		mov byte ptr es:[di+1],00100100B
		add di,2
		inc si
		jmp show_string
		
showStirngRet:
		pop bx
		pop di
		pop cx
		pop es
		pop ds
		
		add di,160	;显示下一行
		add bx,2	;读取下一个字符
		loop showNumber
		
		ret		
;=======================================				
		
code ends
end

这个程序有点问题,明天看
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值