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

版权声明:斌哥版权,如有雷同,纯属虚构 https://blog.csdn.net/iostream992/article/details/83445461

题目:

汇编代码:

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



截图

猜你喜欢

转载自blog.csdn.net/iostream992/article/details/83445461