王爽汇编第三版课程设计1

课程设计一般都是比较综合的题目,考你对之前书上大部分知识点的掌握,而课程设计1在我看来,考的有寻址、打印、子程序设计方面。

我做这题,是按列来打印的,即先打印年份,然后打印年收入,然后打印雇员,最后再打印平均工资。这题我做了很久,期间我差点放弃,一度怀疑自己的智商有问题。后面我把标志寄存器这章看完了,总感觉心里不舒服,没错,就是因为这个课程设计没做出来!

我想过用之前的那个,将这些数据存到table数据段中(就是第7章的那题,要求把这些数据按照一定格式存到table段),然后按行读取,或按列读取。奈何我沿着这个思路做不出来,但是不代表在座的各位也做不出来。程序的设计是灵活多变的,一种程序有N种设计也是很正常的,重要的是找到适合你的那一个,那一个不一定是最好的,但是你理解自己的设计,那么它对你来说,就是最好的。

首先年份可以直接打印,因为是字符串,其次是另外三种类别,需要用到一个不会溢出的除法子程序,具体实现代码请看除法子程序。

然后还需要一个将十六进制转换成十进制的子程序,这个子程序通过连除10来得到余数,依次压栈,打印的时候再依次出栈,这样就可以正序地打印数字了。

最后还需要一个计算一个数字的位数的子程序,将其赋值给CX,这样我们就可以用循环来打印数字。这些就是主要的部分了,接下来放上代码:

assume ds:data,ss:stack,cs:codesg
data segment
	db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985','1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
	dd  16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
	dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226,11542,14430,15257,17800
data ends

stack segment
	dw 16 dup(0)
stack ends

codesg segment
	start:
		mov ax,data
		mov ds,ax
		mov bx,0
		
		mov ax,stack
		mov ss,ax
		mov sp,32
		
		mov ax,0b800h
		mov es,ax
		mov si,0
		mov di,640				
		mov cx,21
	;首先把年份全部打印出来
	printYear:
		push cx
		mov cx,4
		print_year:
			mov al,ds:[bx+si]
			mov es:[di],al
			mov al,7
			mov es:[di+1],al
			inc si
			add di,2
		loop print_year
		sub di,8
		add di,160
		pop cx
	loop printYear
	;接下来开始打印年收入
	mov cx,21
	mov si,0
	mov bx,84
	mov di,680    ;每列的间距是32个字 从第5行开始打印 160*4+8+32
	printAnnualIncome:
		push cx
		mov ax,ds:[bx+si]
		mov dx,ds:[bx+si+2]
		call dtoc
		add si,4
		mov al,2
		mul byte ptr ss:[0]
		sub di,ax
		add di,160
		pop cx
	loop printAnnualIncome
	;接下来打印雇员
	mov cx,21
	mov si,0
	mov bx,168
	mov di,720
	printEmployee:
		push cx	
		mov ax,ds:[bx+si]
		mov dx,0
		call dtoc
		add si,2
		mov al,2
		mul byte ptr ss:[0]
		sub di,ax
		add di,160
		pop cx
	loop printEmployee
	;最后打印平均工资
	mov cx,21
	mov si,0
	mov bx,84
	mov di,756
	printAveragewage:
		push cx	
		mov ax,ds:[bx+si]
		mov dx,ds:[bx+si+2]
		push ax				;这一段是将si的值/2,因为雇员是word,每次只应该加2,而dword应该每次加4
		push dx
		push si
		mov ax,si
		mov dx,2
		div dl
		mov si,ax
		mov cx,ds:[bx+si+84]
		pop si
		pop dx
		pop ax
		call divdw   ;用年收入/雇员 商低位AX 高位DX 再转换成十进制
		call dtoc
		add si,4
		mov al,2
		mul byte ptr ss:[0]
		sub di,ax
		add di,160
		pop cx
	loop printAveragewage
	mov ax,4c00h
	int 21h
dtoc:
		mov cx,10
		call divdw	;得到的商低位在AX,高位在DX,余数在CX
		add cx,30h	;把余数加上30h得到十进制数
		push cx
		mov cx,ax	;把商低位给CX,用JCXZ判断是否已完成
		jcxz ok
		jmp dtoc	
ok:
			;开始计算cx的值
			mov cx,32
			sub cx,sp
			mov ax,cx
			mov cl,2
			div cl
			sub ax,2
			mov cx,ax
			;计算完 开始打印
			mov ss:[0],cx    ;设为计数器 计算数的位数	
			jmp print
print:
		pop ax
		mov es:[di],al
		mov al,7
		mov es:[di+1],al
		add di,2
		dec cx
		jcxz over
		jmp print
	over:
		ret
			
divdw:
	push ax			;将被除数低16位进栈 因为等下要用到
	mov ax,dx		;我们要做32位除法 所以要清空高16位寄存器
	mov dx,0
	
	div cx    		;得到的商在ax 余数在dx
	mov ss:[0],ax 	;暂时保存商 商为式子的商的高16位 这里的商不用左移16位 因为他是保存在另外一个寄存器的
	
	pop ax   		;将ax出栈 因为等下要用到 
	
	div cx      	;现在把dx看做高16位 ax看做低16位 我们做除法 除数是cx
					;现在我们得到了一个商,它为式子的低16位 保存在AX中 余数保存在DX中 
	mov cx,dx		;把余数赋值给CX
	mov dx,ss:[0]     ;把高16位得数取出来 赋值给dx
	ret				;关键的思想是 把rem(H/N)看为一个数的高16位 那么就不用除65536 这样就不会出现乘法溢出了 
codesg ends
end start


运行效果图:


其中dtoc的功能就是将余数压栈,print是打印,ok是计算CX的值,并复制到ss:[0]中,因为后面di要减去ss:[0]*2的值,这样列才能对齐。我的程序设计只是代表了我一个人的思路,现在只是分享给大家,让大家可以从中找找灵感,也希望大家有更好的思路,可以一起交流。

还是那句话,适合自己的方法才是最好的,我想这也是这本书为什么作者没有给出参考答案的原因吧,这样给了读者更大的思考空间,而不是一味地填鸭式教育。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值