XMU汇编语言实验05:子程序设计

本次实验相对上一次实验来说难度稍大,主要是涉及了高级语言中没有手动维护的子程序参数传递。就如在学习笔记中提到的一样,通过变量传递和通过堆栈传递都涉及了堆栈的维护,需要在实践中仔细检查。

实验内容

        

(1)请编写一个子程序,在 STRING 开头的数据区中查找字符串 WE,数据区以$字符作为结束符。如查出,返回此字符所在的地址,若查不到,给’NOT FOUND’ 的提示。

注: 1) 结合题目要求,对于字符串 STRING 的初始化要考虑多种情况,从而得到 不同的输出。 2) 主程序和子程序采用变量传参的方式

 (2) 一个班共有学生若干人,在内存中有一个按学号排列的期末总成绩表,编写 子程序实现按总成绩高低进行排序并将总成绩最高同学的学号输出(假定不 超过两位十进制数)。 1) 若有成绩相同的情况,则按照学号的先后排序。 2) 为了编程方便,可设计少数数据,满足题目要求即可。 3) 参数传递采用寄存器方式。 4) 需利用原有空间进行存储,排序算法任选。

(3) 下述代码段是计算 n! 子程序代码段采用了递归和嵌套结构,n 存放在 AL 中,n!存放在 BX 中。请 结合给出的部分代码完成程序,并绘制出程序调用示意图和堆栈变化示意图。

(4) 有 10 个字节的数据表 array,表内元素已按从小到大的顺序排列好。现给定 一元素 w,试编制子程序,实现在表内查找给定元素 w 的任务,若表内已有 此元素,则显示“Y”;否则,按顺序将此元素插入表中适当的位置。 1) 数据表需要自行进行初始化,数值或字符类型均可; 2) 主程序和子程序之间采用变量方式进行传参。 3) 若主程序和子程序采用堆栈方式进行传参,原始代码将如何修改?

对应程序

(1)注意题中的“考虑多种情况”,其中可能包括原字符串长度小于目标串的情况。当然,在下面的程序中,这种情况也是可以被正确处理的。

;使用变量传参
;打印下标
.MODEL SMALL
.DATA
     STRING  DB 'TWENTY$'
     tar db 'WE'
     ascii db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h
     		db 41h,42h,43h,44h,45h,46h
     msg db 'NOT FOUND',13,10,'$'
.STACK
.CODE
.STARTUP
	push ax
	push si
	push dx
	push cx
	xor ax,ax	;清空AX
	xor si,si
	xor dx,dx
    mov bx,offset string
    call findtar
    pop cx
    pop dx
    pop si
    pop ax
.EXIT

findtar proc
	mov cx,lengthof string	;设置循环次数
	mov si,0	;设置目标串偏移
	;暴力搜索
try:mov al,byte ptr[bx+si]
	cmp al,tar[si]
	jne clr
	inc si	;若相等,递增si
	cmp si,2
	je break
	jmp try	;继续比较下一个字符
clr:xor si,si	;不相等,SI置0
	inc bx	;
	loop try	;下标递增,循环
	;循环完了未找到子串
	mov ax,offset string-1	;AX=-1
	jmp finally
break:mov ax,bx
finally:
    sub ax,offset string
    cmp ax,-1
    jne print
    mov dx,offset msg
    mov ah,9
    int 21h
    jmp endl
print:mov bx,offset ascii
    
    mov dl,al
    mov cl,4
    shr dl,cl
    mov si,dx
    mov dl,byte ptr[bx+si]
    push ax
    mov ah,2
    int 21h
    pop ax
    mov dl,al
    and dl,0fh
    mov si,dx
    mov dl,[bx+si]
    mov ah,2
    int 21h
endl:ret
findtar endp
END

(2)选用冒泡排序算法。其中子程序内部的流程可以直接翻译高级语言。

.model small
.data
	number dw 0001,0002,0003,0004,0005
	score db 17,36,52,53,78
.stack
.code
;排序方法:冒泡排序
;传出参数:DX
;输出一位数字,表示学号
.startup
mov dx,lengthof number
call bubblesort
;下方是输出格式
mov dx,number
add dl,30h
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
.exit 0

bubblesort proc
	mov cx,dx
.repeat
	mov si,0
	mov bx,cx
	dec bx
	.repeat
		mov al,score[si+1]
		.if al>score[si]
			mov dl,score[si]
			mov score[si],al
			mov al,dl
			shl si,1
			mov dx,number[si]
			xchg number[si+2],dx
			mov number[si],dx
			shr si,1
		.endif
		inc si
	.until si>=bx
.untilcxz
ret
bubblesort endp
end

(3)补充后的程序如下,原因已经在注释中说明:

.model small
.data
.code
.startup
main:mov ax,3	;设n=3
	 call fact
xi:	 mov bx,dx
.exit 0
;阶乘子程序
;入口参数:AL中存放n
;出口参数:DX中存放n!
;所用寄存器: CX

fact proc
	cmp al,0
	jnz iia		;AL!=0,iia
	mov dl,1	;AL==0,DL=1
	ret		;(1)
iia:push ax		
dec al		;
	call fact
x2:pop cx
	call mult
x3: mov dx,ax
	ret		;
fact endp
;无符号字节数乘法子程序
;入口参数:CL、DL中各为一乘数
;出口参数:AX中为乘积

mult proc
	mov al,dl
	mul cl
	ret	;(3)
mult endp
	end

假设fact(x)表示n=x时的fact子程序,mult(x)表示n=x的mult子程序,那么子程序调用顺序如下:

Main->fact(3)->fact(2)->fact(1)->fact(0)->fact(1)->mult(1)->fact(1)->fact(2)->mult(2)->fact(2)->fact(3)->mult(3)->fact(3)->main

(4)这是简单的线性表查找,可以直接翻译高级语言对应的操作。

.model small
.stack
.data
	array db 2,4,6,8,10,12,14,16,18,20
	target db 21
.code
.startup

pop ax
pop bx
pop cx
pop dx
pop si
call insert
pop si
pop dx
pop cx
pop bx
pop ax
.exit 0

;使用变量传参
insert proc
	mov cx,lengthof array
	mov dl,target
	mov bx,offset array
	mov si,0
	.while si<cx
	mov al,[bx+si]
	.if al==dl 	;找到对应元素,直接打印'Y'返回
	mov dl,'Y'
	mov ah,2
	int 21h
	mov dl,10
	mov ah,2
	int 21h
	ret
	.endif
	.if al>dl	;元素大于target,直接插入
	.while si<=cx
	xchg dl,[bx+si]
	inc si
	.endw
	ret
	.endif
	;当前元素小于target,查看下一个元素
	inc si
	.endw
	.if si==cx	;若target大于所有数组中的数
	mov [bx+si],dl	;将target放在末尾
	ret
	.endif
insert endp
	end

总结

本次实验涉及的子程序都相对简单,完全可以先用高级语言(例如C)写一遍,再对照高级语言程序,结合汇编语言的高级语言特性,翻译成对应的汇编语言形式。反过来看,汇编语言的高级语言特性也极大地方便了我们书写较为复杂的汇编程序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值