王爽《汇编语言》课程设计1

没想到这个简单的课程设计卡了我4天,前两天做实验室10(这个是为后面的课程设计1做准备),后两天做课程设计1。学汇编也有一个星期了,记录一下。


;这是王爽《汇编语言》课程设计 1
;将实验7中的Power idea公司的数据以一定格式显示在屏幕上
;作者ID:chaoc
;时间:21:14  2012/10/22~2012/10/24...

assume cs:code,ss:stack
stack segment
	dd 8 dup(0)
stack ends

Year segment;每个年份为4个byte
        db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
        db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
        db '1993','1994','1995'
Year ends

;..................................................................................................
Income segment;每年的收入为一个dword型数据,即4个字节
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000
        dd 5937000
Income ends

IncomeStr segment
		  db 21 dup('        ');8个字符 字节 
IncomeStr ends
;..................................................................................................


;..................................................................................................
Employees segment;每年的员工人数为一个word型数据,即2个byte,此段占48个字节
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037
        dw 5635,8226,11542,14430,15257,17800
Employees ends

EmployeesStr segment
			db 21 dup('     ');5个字符 字节 此段占112个字节
EmployeesStr ends
;..................................................................................................


;..................................................................................................

Perincome segment
	dw 21 dup(32)
Perincome ends

PerincomeStr segment
	db 21 dup('   ');3个字符,字节
PerincomeStr ends
;..................................................................................................

Lable segment
	db ' Year       Income  Employees Perincome'
Lable ends

code segment
	start:
			mov ax,stack
			mov ss,ax
;		step0:计算人均收入
			mov ax,Income     		;把收入设为数据段ds +si
			mov ds,ax
			mov ax,Employees			;把员工人数设为扩展段es+di
			mov es,ax
			mov si,0
			mov di,0
			
			mov cx,21
			loop0:
			push cx
			mov dx,ds:[si+2]
			mov ax,ds:[si]
			mov cx,es:[di]
			push dx
			push ax
			push cx
			call divdw
			mov es:[di+160],ax;把人均收入设为es段 es+di+160
			add si,4
			add di,2
			pop cx
			loop loop0
			
;		step1:把Income段中的数据转为字符串保存到IncomeStr段。注意IncomeStr中的结果都是逆序的。
			mov ax,Income;把Income设为数据段 ds+si
			mov ds,ax
			mov ax,IncomeStr;把IncomStr设为扩展段es+di
			mov es,ax
			mov si,0
			mov di,0
			
			mov cx,21
			loop1:
			mov ax,ds:[si+2];依次将每个dword数据的高16位压栈
			push ax
			mov ax,ds:[si];低16位
			push ax
			push es			;存放转换结果字符的扩展段地址入栈
			push di        ;存放字符的偏移地址入栈
			call dtoc
			add si,4
			add di,8
			loop loop1
		
;		step2:把Employees段中的数据转为字符串保存到EmployesStr段。注意EmployeesStr中的结果都是逆序的。
			mov ax,Employees;把Employees设为数据段 ds+si
			mov ds,ax
			mov ax,EmployeesStr;把EmployeesStr设为扩展段es+di
			mov es,ax
			mov si,0
			mov di,0
			
			mov cx,21
			loop2:
			mov ax,ds:[si];依次将每个word数据压栈
			push ax
			push es			;存放转换结果字符的扩展段地址入栈
			push di        ;存放字符的偏移地址入栈
			call wtoc
			add si,2
			add di,5
			loop loop2	
			
;		step3:把Perincome段中的数据转为字符串保存到PerincomeStr段。注意PerincomeStr中的结果都是逆序的。
			mov ax,Perincome;把Perincome设为数据段 ds+si
			mov ds,ax
			mov ax,PerincomeStr;把PerincomeStr设为扩展段es+di
			mov es,ax
			mov si,0
			mov di,0
			
			mov cx,21
			loop3:
			mov ax,ds:[si];依次将每个word数据压栈
			push ax
			push es			;存放转换结果字符的扩展段地址入栈
			push di        ;存放字符的偏移地址入栈
			call wtoc
			add si,2
			add di,3
			loop loop3	
			
;		step4:把IncomeStr,EmployeesStr,PerincomeStr段的数据翻转变为正序
;			step4.1把IncomeStr段的数据转为正序
			mov ax,IncomeStr
			mov ds,ax
			mov si,0
			mov ax,8
			mov cx,21
			step4loop1:
			push ds
			push si
			push ax
			call ReverseStr
			add si,8
			loop step4loop1
;			step4.2把EmployeesStr段的数据转为正序
			mov ax,EmployeesStr
			mov ds,ax
			mov si,0
			mov ax,5
			mov cx,21
			step4loop2:
			push ds
			push si
			push ax
			call ReverseStr
			add si,5
			loop step4loop2
;			step4.3把PerincomeStr段的数据转为正序
			mov ax,PerincomeStr
			mov ds,ax
			mov si,0
			mov ax,3
			mov cx,21
			step4loop3:
			push ds
			push si
			push ax
			call ReverseStr
			add si,3
			loop step4loop3
						
			
;		step5:把数据显示到屏幕上,即把表格数据发送到显示缓冲区
;			step5.0在显示数据前先清屏
			call clear
			
;			step5.1把年份发送到显示缓冲区
			mov ax,Year
			mov ds,ax
			mov si,0 ;要显示的字符首地址
			mov dl,1 ;列号
			mov dh,4 ;行号
			mov bh,4 ;字符个数
			mov bl,00000010B;颜色
			mov cx,21
			step5loop1:
			push dx
			push bx
			push ds
			push si
			call showstr
			inc dh
			add si,4
			loop step5loop1
;			step5.2把总收入IncomeStr段的数据发送到显示缓冲区
			mov ax,IncomeStr
			mov ds,ax
			mov si,0 ;要显示的字符首地址
			mov dl,10 ;列号
			mov dh,4  ;行号
			mov bh,8 ;字符个数
			mov bl,00000100B;颜色
			mov cx,21
			step5loop2:
			push dx
			push bx
			push ds
			push si
			call showstr
			inc dh
			add si,8
			loop step5loop2
;			step5.3把员工人数即EmpoyeesStr段的数据发送显示缓冲区
			mov ax,EmployeesStr
			mov ds,ax
			mov si,0 ;要显示的字符首地址
			mov dl,20 ;列号
			mov dh,4  ;行号
			mov bh,5 ;字符个数
			mov bl,00000001B;颜色
			mov cx,21
			step5loop3:
			push dx
			push bx
			push ds
			push si
			call showstr
			inc dh
			add si,5
			loop step5loop3
;			step5.4把人均收入即PerincomeStr段的数据发送到显示缓冲区
			mov ax,PerincomeStr
			mov ds,ax
			mov si,0 ;要显示的字符首地址
			mov dl,30 ;列号
			mov dh,4  ;行号
			mov bh,3 ;字符个数
			mov bl,00000101B;颜色
			mov cx,21
			step5loop4:
			push dx
			push bx
			push ds
			push si
			call showstr
			inc dh
			add si,3
			loop step5loop4
;			step6:在数据的最前面显示栏目标签
			mov ax,Lable
			mov ds,ax
			mov si,0
			mov dl,0
			mov dh,2
			mov bl,00000010B
			mov bh,40
			
			push dx
			push bx
			push ds
			push si
			call showstr
			
			;主函数结束
			mov ax,4c00h
			int 21h
;............................................................................................................................................................
;............................................................................................................................................................
;...........................................................上面是主程序.....................................................................................
;..........................................................下面是要调用的几个函数............................................................................
;............................................................................................................................................................
;............................................................................................................................................................
	divdw:	push bp
				push bx
				mov bp,sp
					
				mov cx,[bp+6];除数
				mov ax,[bp+10];高16位
				mov dx,0
				div cx;现在AX中是高16位除n的商,DX中是余数
				push ax;把高16位的除到得商保存到栈里
				
				mov ax,[bp+8];现在dx中是高16位除到的余数,ax中是低16位
				div cx
				mov cx,dx
				pop dx;现在dx中时高16除到得商,ax中是低16位除到得商,cx中是余数
				
				pop bx
				pop bp
				ret 6
		;divdw函数结束
	dtoc:		
				push ax
				push bx
				push cx
				push ds
				push si
				push bp
				mov bp,sp
				
				mov dx,[bp+20];数据的高16位
				mov ax,[bp+18];数据的低16位
				mov ds,[bp+16];段地址
				mov si,[bp+14];偏移地址
				
			dtocs1:
				push dx
				push ax
				mov cx,10
				push cx
				call divdw
				add cx,30H
				mov ds:[si],cl;把转换后的字符送到指定的数据区域
				add si,1
				mov cx,ax
				jcxz dtoctestagain;判断商的低16位是不是0
			dtocs2:
				mov cx,10
				jmp dtocs1
		  	dtocwordsend:	
		  		pop bp
		  		pop si
		  		pop ds
		  		pop cx
		  		pop bx
		  		pop ax
		  		ret 8
		  dtoctestagain:
		  		mov cx,dx;判断商的低16位后再判断商的高16位是不是0
		  		jcxz dtocwordsend;如果都是0就跳到wordsend,准备跳除函数
		  		jmp dtocs2;不是0回到前面继续执行
		  ;函数dtoc结束
		  wtoc:		
				push ax
				push bx
				push cx
				push ds
				push si
				push bp
				mov bp,sp
				
				mov dx,0			;数据的高16位
				mov ax,[bp+18];数据的低16位
				mov ds,[bp+16];段地址
				mov si,[bp+14];偏移地址
				
			wtocs1:
				push dx
				push ax
				mov cx,10
				push cx
				call divdw
				add cx,30H
				mov ds:[si],cl;把转换后的字符送到指定的数据区域,转换后的字符只占据cl
				add si,1
				mov cx,ax
				jcxz wtocwordsend
				mov cx,10
				jmp wtocs1
		  	wtocwordsend:	
		  		pop bp
		  		pop si
		  		pop ds
		  		pop cx
		  		pop bx
		  		pop ax
		  		ret 6
   ;wtoc函数结束
   
   	showstr:	
				push ax
				push bx
				push cx
				push dx
				push ds
				push es
				push si
				push di
				push bp
				
				mov bp,sp
				mov dx,[bp+26];行号dh,列号dl
				mov bx,[bp+24];bl颜色值,bh个数
				mov ds,[bp+22];段地址
				mov si,[bp+20];偏移
				
				mov di,0H;屏幕的偏移
				;接下来计算行号和列号带来的偏移di的初值
				push bx;bx寄存器要用到
				mov al,dh;开始计算行号带来的偏移
				mov ah,0
				mov bl,160
				mul bl
				add di,ax;把计算行号带来的偏移值加到di上
				mov al,dl;开始计算列号带来的偏移
				mov ah,0
				mov bl,2
				mul bl
				add di,ax;把计算列号带来的偏移加到di上
				pop bx;恢复bx的值
				
				mov ax,0B800H;显示缓冲区的起始地址
				mov es,ax
				
				mov ch,0
				mov cl,bh      	;把bh的值复制给cl用作循环次数
				showstrloop:
				mov bh,ds:[si]    ;这里bh为要显示的字符了
				mov es:[di],bh
				mov es:[di+1],bl	;颜色值
				inc si
				add di,2
				loop showstrloop
					
				pop bp
				pop di
				pop si
				pop es
				pop ds
				pop dx
				pop cx
				pop bx
				pop ax
				ret 8
	;show_str ends
	ReverseStr:
		push ax
		push ds
		push si
		push cx
		push bp
		
		mov bp,sp
		
		mov ds,[bp+16];取得3个参数
		mov si,[bp+14]
		mov cx,[bp+12]
		
		ReverseStrloop1:;把字符串取出来,存到栈中,再出栈实现顺序逆转
		mov al,ds:[si] ;字符串中的字符是byte型。用word装住它再压栈
		push ax
		inc si
		loop ReverseStrloop1
		
		mov cx,[bp+12] ;由于cx和si的值在上面已经改变,现在须重新赋值
		mov si,[bp+14]
		ReverseStrloop2:
		pop ax          ;依次出栈,实现逆序
		mov ds:[si],al
		inc si
		loop ReverseStrloop2
		
		pop bp
		pop cx
		pop si
		pop ds
		pop ax
		
		ret 6
		;函数ReverseStr结束
		clear:
		push ds
		push si
		push ax
		push cx
		
		mov ax,0B800H
		mov ds,ax
		mov si,0
		mov cx,0FFFFH;25*80的缓冲区,2000个字符
		clearloop:
		mov ax,0000011100100000b
		mov ds:[si],ax
		add si,2
		loop clearloop
		
		pop cx
		pop ax
		pop si
		pop ds
		ret
		;clear函数结束
code ends
end start


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值