汇编语言:编写子程序(下)课程设计1

本文介绍了一段复杂的汇编代码,该代码用于处理公司21年的财务数据,包括年份、总收入和雇员人数,并将其转换为屏幕上的可视信息。通过多个循环和子程序调用,代码实现了数据的读取、转换和显示,展示了汇编语言的强大功能。

题目:

汇编代码:

assume cs:codesg
data segment
	db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
	db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
	db '1993','1994','1995'
	;以上是表示21年的21个字符串
	dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
	dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
	;以上是表示21年公司总收入的21个dword型数据
	dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
	dw 11542,14430,15257,17800
	;以上是表示21年公司雇员人数的21个word型数据
data ends
 
table segment
	db 21 dup ('year sumn ne ?? ')
table ends
 
data_string segment
	db 10 dup (0)
data_string ends
 
stack segment
	db 16 dup (0)
stack ends
 
codesg segment
start:

;################之前的那个代码##################
 mov ax,data
 mov ds,ax

 mov ax,table
 mov es,ax



 mov di,0
 mov bx,0
 mov si,0
 mov cx,21

 s:
 

 ;复制年份 year

 mov ax,[si]
 mov es:[bx],ax

 mov ax,[si+2]
 mov es:[bx+2],ax

 

 ;复制总收入 summ

 mov ax,[si+84]
 mov es:[bx+5],ax

 mov dx,[si+84+2];高位直接存在dx
 mov es:[bx+5+2],dx

 ;复制雇员人数 ne

 mov bp,[di+168]
 mov es:[bx+10],bp

 div word ptr es:[bx+10]

 ;商,余数在dx中
 mov es:[bx+13],ax

  add bx,16
  add si,4
  add di,2
 loop s 
;################################################


;################新增加显示在屏幕上##############
;##################写成四个循环##################
	mov ax,data_string
	mov ds,ax
	mov si,0	;ds:[si]指向字符串首地址
	mov ax,stack
	mov ss,ax
	mov sp,10H
	mov di,1
	mov bx,0
	mov cx,21
 year:
        push cx
	mov si,0	
	mov cx,4
 s_year:
        mov al,es:[bx+si]
	mov ds:[si],al
	inc si
	loop s_year
	inc di
	mov ax,di
	mov dh,al    ;行号
	mov dl,12    ;列号
	mov cl,2
	mov si,0
	call show_str
	pop cx
	add bx,10H
	loop year
;************************************************
     
;************************************************
	mov di,1
	mov bx,0
	mov si,0
	mov cx,21
  sumn:	
        push cx
	mov ax,es:[bx+5]
	mov dx,es:[bx+7]
	call dwtoc
	inc di
	mov ax,di
	mov dh,al
	mov dl,23
	mov cl,0ah
	mov si,0
	call show_str
	pop cx
	add bx,10H
	loop sumn
;************************************************

;************************************************
	mov di,1
	mov bx,0
	mov si,0
	mov cx,21
 ne:	
        push cx
	mov ax,es:[bx+0aH]
	mov dx,0
	call dwtoc
	inc di
	mov ax,di
	mov dh,al
	mov dl,35
	mov cl,0ch
	mov si,0
	call show_str
	pop cx
	add bx,10H
	loop ne
;************************************************

;************************************************
	mov di,1
	mov bx,0
	mov si,0
	mov cx,21
  xx:	push cx
	mov ax,es:[bx+0dH]
	mov dx,0
	call dwtoc
	inc di
	mov ax,di
	mov dh,al
	mov dl,45
	mov cl,06h
	mov si,0
	call show_str
	pop cx
	add bx,10H
	loop xx

;************************************************

;************************************************
 
	mov ax,4c00H		
	int 21H

; ###############################################
; ####                                       ####
; ####             子  程  序                ####
; ####                                       ####
; ###############################################

;###################show_str#####################
;名称:show_str
;功能:在指定位置,用指定颜色,显示一个用0结束的字符串
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79)
;      (cl)=颜色,ds:si指向字符串首地址
;返回:无

 show_str:
	  push ax
	  push bx
	  push cx
	  push dx
	  push si
	  push es
	  			
	  
	  
	  show_str_start:
	  			
	  mov ax,0b800h
	  mov es,ax
	  			
	  ; 计算行偏移 ,结果在ax中
	  mov al,160
	  mul dh   
	  			
	  ; 计算列偏移 ,结果在dx中
	  mov dh,0
	  add dx,dx
	  			
	  ;计算总偏移,结果放在bx中
	  mov bx,ax
	  add bx,dx
	  			
	  ;到目前,es:[bx]指向目标显存
	  mov dl,cl
	  			
	  			
 string_copy:
	  mov cl,[si]
	  mov ch,0
	  jcxz string_copy_ok  ;当(ds:[si])==0时跳出循环
	  mov es:[bx],cl
	  mov es:[bx+1],dl
	  inc si
	  add bx,2						
	  jmp short string_copy
	  			
	  			
	  			
string_copy_ok:
	  			
	  pop es
	  pop si
	  pop dx
	  pop cx
	  pop bx
	  pop ax
	  ret
;####################divdw#######################
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数:(ax)=dword型数据低16位,(dx)=dword型数据高16位,(cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数
;应用举例:计算1000000/10(f4240H/0aH)
 
divdw:
	  
	  
	  push bx	
	  push ax
	  ; 被除数高位除CX   27/2  -->   AX 商  DX 余数
	  mov ax,dx
	  mov dx,0
	  div cx

	  mov bx,ax   ;商的高16位暂时存放在BX中
				 			 
        ; 商在AX中,余数在DX中
	; 余数就是最终的余数放到CX中去,商就是最终的商的低16位,不用动!
	  pop ax
	  div cx
				 
	  mov cx,dx
	  mov dx,bx			 
	  pop bx
	  ret
;###################dtoc#########################
;名称:dwtoc
;功能:将dword型数据转变为表示十进制数的字符串,字符串以0为结尾符。
;参数:(ax)=dword型数据的低16位,(dx)=dword型数据的高16位,ds:si指向字符串的首地址
;返回:无


dwtoc:
  mov cx, 0
  push cx

s_dwtoc:
  mov cx,10; 除数
  call divdw; 余数在cx中

  add cx,30h
  push cx; 保存余数的ASCII形式

  ; 判断是否商为0,如果高低16位都为0,则返回
  mov cx,dx
  jcxz ok_dxz;
  
  ; 高位不为0,则直接跳回,继续执行运算
  jmp short s_dwtoc

  ; 商的高位为0
  ok_dxz:
  mov cx,ax
  jcxz ok_axz
  jmp short s_dwtoc

  ; 商的低位为0
  ok_axz:
  ; 赋值到 ds:[si]
  mov dx, si; 保存si,si为字符串的首地址
  loop_dtoc:
  pop cx
  mov ds:[si], cl
  jcxz end_dwtoc
  inc si
  jmp short loop_dtoc
   mov si, dx

  end_dwtoc:
  mov ax, 0
  mov ds:[si], ax
  mov si,dx
  ret

	  
;#######################################################
	
codesg ends
end start

运行截图:

 


代码完善(增加一个延时代码,可以竖的一列一列刷新) 

delay:	
				push cx	
				mov cx,30h
				delay_s1:
							push cx
							mov cx,0
							delay_s2:
									
							loop delay_s2
							pop cx
				loop delay_s1
		
				pop cx
		ret

课上的另外一种实现(增加一个延时代码,可以横的一行一行刷新) 

assume cs:code,ss:stack
 
data segment
	;  bx= 0
	db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
	db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
	db '1993','1994','1995'
	;以上是表示21年的21个字符串
	
	;bx+84
	dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
	dd 245980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
	;以上是表示21年公司总收入的21个dword型数据
	
	
	; bp = 168
	dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
	dw 11542,14430,15257,17800
	;以上是表示21年公司雇员人数的21个word型数据
	
	
data ends
 
table segment
	db 21 dup ('year    x          y        z  ',0)  		
	            ; 0       ;8         ;19      ;28   
table ends

stack segment
	db 64 dup(0)	
stack ends


code segment
start:	

		mov ax,stack
		mov ss,ax
		mov sp,64
		
		mov ax,data
		mov es,ax
		mov bx,0
		mov bp,168
		
		mov ax,table
		mov ds,ax
		mov si,0
		
		mov cx,21
		
		
		pidea_21:
					;复制年份				
					mov ax,es:[bx]
					mov [si],ax
					mov ax,es:[bx+2]
					mov [si+2],ax
					
					
					;将总收入转换为字符串后,复制到table段中 ds:(si+8)
					
					mov ax,es:[bx+84]
					mov dx,es:[bx+84+2]
					
					push si				
					add si,8
					call dtoc
					pop si
		
					;将雇员人数转换为字符串后,复制到table段中 ds:(si+19)
					
					mov ax,es:[bp]
					mov dx,0
					
					push si				
					add si,19
					call dtoc
					pop si
					
					;计算平均收入后转换为字符串,再复制到table段中 ds:(si+28)
					
					mov ax,es:[bx+84]
					mov dx,es:[bx+84+2]
					div word ptr es:[bp]
					
					; ax 存放的就是平均收入
					mov dx,0			
					push si
					add si,28
					call dtoc
					pop si
					
					
					;计算行号的问题?
					; si/32
					
					mov ax,si
					push bx
					push cx
					mov bl,32
					div bl
					mov dh,al   ;行号进dh
					mov dl,0
					mov cl,2h
					call show_str
					pop cx		
					pop bx
					
				  call delay		
										
					add bx,4
					add bp,2
					add si,32
							
		
		loop pidea_21
	
		
		mov ax,4c00h
		int 21h
		
		;  延时子程序delay
		
		delay:	
				push cx	
				
				mov cx,30h
				delay_s1:
							push cx
							mov cx,0
							delay_s2:
									
							loop delay_s2
							pop cx
				loop delay_s1
		
				pop cx
		ret
		
		
	  ; 显示字符串子程序show_str
	  ; 参数1 ds:si指向要显示的字符串首地址,字符串以0结尾
	  ; 参数2 行号dh(0~24) 
	  ; 参数3 列号dl(0~79)
	  ; 参数4 颜色属性 cl 
	  
	  
	  show_str:
	  			push ax
	  			push bx
	  			push cx
	  			push dx
	  			push si
	  			push es
	  			
	  
	  
	  show_str_start:
	  			
	  			mov ax,0b800h
	  			mov es,ax
	  			
	  			; 计算行偏移 ,结果在ax中
	  			mov al,160
	  			mul dh
	  			
	  			; 计算列偏移 ,结果在DX中
	  			mov dh,0
	  			add dx,dx
	  			
	  			;计算总偏移,结果放在BX中
	  			mov bx,ax
	  			add bx,dx
	  			
	  			;到目前,es:[bx]指向目标显存
	  			mov dl,cl
	  			
	  			
	  			string_copy:
	  					mov cl,[si]
	  					mov ch,0
	  					jcxz string_copy_ok
	  					mov es:[bx],cl
	  					mov es:[bx+1],dl
	  					inc si
	  					add bx,2						
	  			jmp short string_copy
	  			
	  			
	  			
	  	string_copy_ok:
	  			
	  			pop es
	  			pop si
	  			pop dx
	  			pop cx
	  			pop bx
	  			pop ax
	  			
	  	ret
	  
	  
	  
	  
	  ; 解决除法溢出的子程序divdw
	  ; 参数1 被除数 dx+ax 32位组合
	  ; 参数2 除数 cx
	  ; 返回值 商:dx+ax   余数: cx
	  
	  
	  divdw:
	  
	  
	  		 push bx	
	  		 push ax
	  		 
	  		 ; 被除数高位除CX   27/2  -->   AX 商  DX 余数
	  		 mov ax,dx
	  		 mov dx,0
	  		 div cx

				 mov bx,ax   ;商的高16位暂时存放在BX中
				 			 
				 ; 商在AX中,余数在DX中
				 ; 余数就是最终的余数放到CX中去,商就是最终的商的低16位,不用动!
				 pop ax
				 div cx
				 
				 mov cx,dx
				 mov dx,bx			 
				 
				 pop bx
	  ret
	  
	  
	  
	  ;   改进后的dtoc  子程序,支持转换dword型数据
	  ;  参数1  ds:si 指向最终字符串首地址
	  ;  参数2  待转换的dword型数据  dx(高位)+ax(低位)
	  
	  dtoc:
	  			push ax
	  			push bx
	  			push cx
	  			push dx
	  			push si
	  			push di
	  			
	  
	  dtoc_start:
	  			mov di,0   ; 用di 存放压入的数据个数
	  			pick:
	  				
	  					mov cx,10    ;divdw子程序中的除数,被除数不用动
	  				  call divdw
	  					add cx,30h
	  					push cx
	  					inc di
	  					mov cx,dx
	  					jcxz next
	  					jmp short pick
	  					
	  					next:	  					
	  					mov cx,ax
	  					jcxz pick_ok
	  				 	jmp short pick
	  			
	  			
	  			pick_ok:
	  					mov cx,di  ; 确定弹出的数据个数
	  					
	  			; 堆栈中的数据出栈,送到目标内存位置
	  			
	  			dtoc_move:
	  						pop ax
	  						mov ds:[si],al
	  						inc si  			
	  			loop dtoc_move
	  			
	  			; 在字符串末尾添加一个结束符0
	  			;mov byte ptr [si],0
	  			
	  			
	  			
	  			
	  			pop di
	  			pop si
	  			pop dx
	  			pop cx
	  			pop bx
	  			pop ax
	  			
  		
	  ret
	  
	  
		
	
code ends
end start



截图

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值