汇编实验10 编写子程序

1.显示字符串
assume cs:codesg
data segment 
	db 'Welcome to masm!',0
data ends
stack segment
	db 16 dup (0)
stack ends

codesg segment
start:		mov dh,0		;行  0~23
		mov dl,0		;列  0~79  可以80,但会到下一行,dl*2<255就行
		mov cl,2		;颜色
		mov ax,data
		mov ds,ax
		mov si,0
		mov di,0
		call show_str
	
back:		mov ax,4c00h
		int 21h

show_str:
		mov ax,stack 
		mov ss,ax
		mov sp,10h	
		call get_row		;计算得出行存在es
		call calc_col   	;计算在显存中真正列的地址
	
	
lpc:		call get_col    	;计算得出列存在di 下一行列在dx
					;列是0 2 4 6....偶数的

		push cx			;保存颜色	
		mov ah,cl		;写入显存的颜色
		mov al,ds:[si]		;写入显存的字
		mov es:[di],ax		;写入显存 
		inc si

		mov ch,0		;内容为0 跳转
		mov cl,ds:[si]		
		jcxz back
		pop cx 			;恢复颜色
		jmp lpc


get_row:
		push cx			;保存颜色
		push dx			;保存行列

		mov ax,0B80ah
		mov dl,dh		;行小于255 用低8位就行
		mov dh,0
		mov cx,dx
		add cx,1		;保证cx>=1
lp1:	add ax,10
		loop lp1
		sub ax,10		;减掉因为cx为0时多加的		
		pop dx			;恢复行列
		pop cx			;恢复颜色
		mov es,ax		;算出行
		ret

get_col:
		push dx			;保存行列 
		mov dh,0
		mov di,dx
		pop ax			;恢复行列到中继寄存器ax
		mov dh,ah		;取原行
		mov dl,al		;取原列
		add dl,2		;列+2	 行列结果存在dx中
		ret

calc_col:
		push dx			;保存行列 
		mov al,dl		;列作为被乘数
		mov dl,2		;*2
		mul dl			;结果不会超过160   因为只有80列
		pop dx			;恢复行
		mov dl,al		;保存真正的列到dl 
		ret

codesg ends

end start

### 汇编语言实验编写子程序 示例教程 在汇编语言中,编写子程序是一项重要的技能。子程序可以用来实现特定的功能,并且可以在程序的多个地方调用,从而提高代码的可重用性和可维护性。以下是一个关于实验十中编写子程序的示例教程[^3]。 #### 1. 子程序的基本结构 子程序通常由以下几个部分组成: - **入口点**:子程序开始执行的位置。 - **参数传递**:通过寄存器或堆栈将参数传递给子程序。 - **保护现场**:保存子程序调用前的状态(如寄存器值)。 - **核心逻辑**:实现子程序的主要功能。 - **恢复现场**:恢复子程序调用前的状态。 - **返回指令**:使用 `ret` 指令返回到调用位置。 #### 2. 示例:数字转换为字符串 根据引用内容,实验十要求将一个数字转换为字符串并显示在屏幕上。以下是实现该功能的子程序示例: ```asm assume cs:code, ds:data data segment num dw 12666 ; 待转换的数字 str db 10 dup(0) ; 存储转换后的字符串 data ends code segment start: mov ax, data mov ds, ax lea si, str ; SI 指向字符串缓冲区 mov ax, [num] ; AX = 数字 call num_to_str ; 调用子程序将数字转换为字符串 mov ah, 9 ; DOS 显示字符串功能 lea dx, str ; DX 指向字符串 int 21h ; 调用 DOS 中断 mov ax, 4c00h ; 程序结束 int 21h ; 子程序:将 AX 中的数字转换为字符串,存储到 SI 指向的缓冲区 num_to_str proc push ax ; 保护 AX push bx ; 保护 BX push cx ; 保护 CX push dx ; 保护 DX xor cx, cx ; CX 用于计数 convert_loop: xor dx, dx ; 清零 DX mov bx, 10 ; 除数为 10 div bx ; AX = 商,DX = 余数 add dl, '0' ; 将余数转换为 ASCII 字符 push dx ; 将字符压入堆栈 inc cx ; 计数器加 1 test ax, ax ; 判断商是否为 0 jnz convert_loop ; 如果不为 0,继续循环 store_chars: pop dx ; 从堆栈弹出字符 mov [si], dl ; 存储到字符串缓冲区 inc si ; 指针加 1 loop store_chars ; 继续存储直到计数器为 0 mov byte ptr [si], '$'; 添加字符串结束标志 pop dx ; 恢复 DX pop cx ; 恢复 CX pop bx ; 恢复 BX pop ax ; 恢复 AX ret ; 返回 num_to_str endp code ends end start ``` #### 3. 关键点解析 - **数字转换为字符串**:通过不断对数字取余数和整除操作,将每一位数字提取出来并转换为对应的 ASCII 字符。 - **堆栈的使用**:由于数字的位数是从低位到高位依次计算的,而字符串需要从高位到低位存储,因此使用堆栈来反转顺序。 - **保护和恢复寄存器**:在子程序中,为了不影响主程序的寄存器状态,需要在进入子程序时保存寄存器值,并在退出时恢复。 #### 4. 显示字符子程序 为了显示字符串,可以使用 DOS 中断功能 `INT 21H` 的 `AH=9` 功能。以下是显示字符串的子程序示例: ```asm show_str proc push ax ; 保护 AX push dx ; 保护 DX mov ah, 9 ; DOS 显示字符串功能 int 21h ; 调用 DOS 中断 pop dx ; 恢复 DX pop ax ; 恢复 AX ret ; 返回 show_str endp ``` #### 5. 注意事项 - 确保字符串以 `$` 结尾,这是 DOS 显示字符串功能的要求。 - 在编写子程序时,注意保护和恢复寄存器,以免影响主程序的运行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值