(十六)《汇编语言(王爽)》 | 实验 10:编写子程序

本文介绍了汇编语言编程中的模块化设计,通过call和ret指令实现子程序调用。实验涉及显示字符串、解决除法溢出问题以及将数值转换为十进制字符串并显示。在显示字符串任务中,详细阐述了如何在指定位置以指定颜色显示字符串。在解决除法溢出问题中,提出了一种避免16位除法溢出的算法。最后,展示了将16位数据转换为十进制字符串的实现过程。


1. 预备知识

  • call 标号 将当前 IP 的内容入栈,并且根据位移跳转到执行标号处;ret 将栈顶元素赋值为 IP 寄存器,二者都是段内转移。由此,call 和 ret 指令共同支持了汇编语言编程中的模块化设计,类似于高级语言中的函数机制。如计算 N 的 3 次方:
call cube		;调用子程序
...
cube:
	mov ax,bx
	mul bx
	mul bx
	ret			;返回
  • 用寄存器来存储参数和结果是最常用的方法,对于存放参数的寄存器和存放结果的寄存器,调用者和子程序的读写操作相反:调用者将参数送入参数寄存器,从结果寄存器取返回值;子程序从参数寄存器取参数,将结果送入结果寄存器。
  • 在使用寄存器时我们希望:调用子程序时不必关系程序使用了哪些寄存器编写子程序时不必关心调用者使用了哪些寄存器不会发生寄存器冲突。解决办法是在程序的开始将所有用到的寄存器中的内容使用栈保存,然后在子程序返回前恢复:
子程序开始:
	子程序使用的寄存器入栈
	子程序的内容
	子程序使用的寄存器出栈
	ret
  • 汇编语言中的除法规则:如果除数为 8 位则被除数为 16 位,默认存放在 AX 中,且 AL 存放商、AH 存放余数;如果除数为 16 位则被除数为 32 位,且高 16 位存放在 DX 中、低 16 位存放在 AX 中,且 AX 存放商、DX 存放余数。

2. 实验任务 1:显示字符串

在指定的位置,用指定的颜色,显示一个用 0 结束的字符串。参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si 指向字符串的首地址。如在屏幕的 8 行 3 列,用绿色显示 data 段中的字符串

assume cs:code

data segment
	db 'Welcome to masm!',0
data ends

code segment
start:
	mov dh,8		;行号
	mov dl,3		;列号
	mov cl,2		;颜色
	mov ax,data
	mov ds,ax		;段寄存器DS指向数据段data
	mov si,0	
	call show_str	;调用子程序
	
	mov 4c00h
	int 21h
	
show_str:
	...			;待完成部分
code ends 
end start
  • 由于需要显示有颜色的字符串,所以使用 80×25 彩色模式。每个字符占用 2 个字节,低位存储 ASCII 码、高位存储属性。一屏幕共占用 4000 字节,可存储 2000 个字符,共 25 行,每行 80 个字符。
  • 由于写入位置的行号为 DH 的内容、列号为 DL 的内容,且每行的字节数为 160,所以可以使用乘法定位写入位置的起始位置(列的索引类似)。这里,使用两个 8 位寄存器做乘法:
mov al,160	;8位寄存器乘法,一个存在AL中,另一个存在寄存器或内存单元(DH)中
mul dh		;定位行的偏移,乘法结果存放在AX中
mov bx,ax	;以防被下一个乘法覆盖,这里需要保存寄存器AX的内容,如BX
mov al,2
mul dl		;定位列的偏移,乘法结果存放在AX中
add bx,ax	;最终的偏移
  • 由于事先不知道 data 段中字符串的长度,题目给出字符串的用 0 结束。jcxz 标号的功能是当寄存器 CX 的内容为 0 时则跳转到标号执行。所以,我们可以使用寄存器 CX 来接收字符串中的内容,并使用 jcxz 指令来判断是否到达字符串结尾
  • 由于不知道循环次数,这里使用 jmp 指令配合 jcxz 来完成循环功能
help:
	mov cl,data:[]		;将data段字符串依次写入C
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值