现在的位置: 首页 > 综合 > 正文

课程设计1

2018年04月06日 ⁄ 综合 ⁄ 共 4187字 ⁄ 字号 评论关闭
弄了两天多才搞定,累死我了。。。。。

assume cs:codesg,ds:data,es:table
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个字符串  0~53H
	 
	 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型数据  54H~0A7H
	 
	 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型数据	0A8H~0D1H
data ends

table segment
     db 21 dup ('year sumn ne ?? ')
table ends

codesg segment
start:mov ax,data		
	  mov ds,ax
	  mov ax,table		;表
	  mov es,ax
	  
	  xor bx,bx
	  xor si,si
	  xor di,di
	  mov cx,21
	  
	  call s
	  
	  mov dh,8
	  mov dl,3
	  mov cl,2
	  call year_s
	  mov ax,4c00H
	  int 21H
	  
	s:mov ax,ds:[bx]              
	  mov es:[si],ax		   ;19
	  mov ax,ds:[bx].2			   ;75
	  mov es:[si].2,ax
	  
	  mov ax,ds:[di].0A8H
	  mov es:[si].0AH,ax
	  
	  mov ax,ds:[bx].54H
	  mov es:[si].5H,ax
	  mov dx,ds:[bx].56H
	  mov es:[si].7H,dx
	  
	  div word ptr es:[si].0AH
	  mov es:[si].0DH,ax
	  
	  add bx,4   ;因为年份和总收入都为4字节,人数为2字节
	  add di,2
	  add si,10H
	  
	  loop s  
	  ret
;==============================================|
;----------------年份子程序--------------------|
;==============================================|	  
year_s:push cx					;年份子程序
     mov bx,0
	 mov si,0					
  c2:mov ax,0B800H				;显存地址
     mov ds,ax
	 mov al,0a0h				
	 mul dh               ;8*160 要写入的偏移地址
	 mov bx,ax			  ;(bx)=(ax)
	 mov al,2
	 mul dl               ;起始地址
	 add bx,ax			  ;(bx)=(bx)+(ax)
	 pop dx				  ;将cx中的值弹出栈放置dx里			 
	 mov cx,4			  ;外层循环数
   k:push cx			  
	 push bx
	 push si				;入栈是因为后面要用到这些
     mov cx,21				;内层循环数
   k2:mov al,es:[si]		;es段为表段,此时si为0,取出其中字符
	 mov ah,dl				;原始cl里存放的是颜色属性信息,现在放入ah
	 mov ds:[bx],ax			;将ax中值放入ds:[内存单元]
	 add si,10H				;指向下一行,此时指向的字符是与开始si所对应位置的字符了   检索位置
	 add bx,0A0H			;bx为显存地址区偏移,(bx)=(bx)+0A0H,即字符输出的位置指向下一行与开始bx所对应位置的字符   输出位置
	 loop k2
	
	 pop si					;先前将si push进栈是为了混乱,现在pop 出来自加1 ,即指向要检索的下一个字符
	 inc si

	 pop bx					;将bx pop出栈加2,因为一个字节存放字符,一个存放属性
	 add bx,2
	 pop cx					;将cx的值还给它

	 loop k					;跳至外层循环检索下一字符
	 add bx,20				
	 push bx				;bx记录了写入年份的偏移,现在保存起来,用作总收入写入的起始偏移地址
;==============================================|
;----------------总收入子程序------------------|
;==============================================| 
icome:mov bx,0
	 pop si					;将年份的偏移地址pop出栈到si中,用作总收入写入的起始偏移地址
	 mov cx,21				;循环次数
	 mov bp,0				;bp定位es段中要查询的首地址,bp用作索引es段中的数据位置
	 mov di,si				;将要写入的起始偏移地址放到di中,di用作屏幕写入位置定位
	 push di
	 
icome2:push cx				;将循环次数入栈保存,以免后继操作将cx打乱
     mov ax,es:[bp+5]       ;ax为低16位,es:[bp+5],指向了es段中第5个字节
	 mov dx,es:[bp+7]       ;dx为高16位,es:[bp+7],指向了es段中第7个字节
	 call dwtoc				;跳转到dtoc,dtoc功能是将dword数据转换为十进制输出
	 add bp,10H				;初始bp为0,表明从0索引,现在bp加上10H(16),因为es段的长度为16个字节,现在加上16,表示将索引下一行与上一行对应的字符处,即索引第二行了
	 pop cx					;将循环次数pop出栈到cx中
	 loop icome2	 
	 
;==============================================|
;------------------人数子程序------------------|
;==============================================| 
number:pop si
       add si,30
       mov cx,21
	   mov bp,0
	   mov di,si
	   push di
number1:push cx
        mov ax,es:[bp+0AH]
		call dtoc
		add bp,10H
		pop cx
		loop number1
       
;==============================================|
;---------------平均工资子程序-----------------|
;==============================================| 
wage:pop si
     add si,30
	 mov cx,21
	 mov bp,0
	 mov di,si
wage1:push cx
      mov ax,es:[bp+0DH]
	  call dtoc
	  add bp,10H
	  pop cx
	  loop wage1
	  ret	 
	  
dwtoc:mov cx,0				;
     push cx
	 
dwtoc1:mov cx,10				;cx为除数
      call divdw			;跳转到divdw中,做不会溢出的除法运算
	  add cx,30H			;cx存放的是最后一次运算所得的余数,现在加30H,是为了得到它的ASCII码
	  push cx				;保存余数的ASCII码进栈
	  mov cx,dx             ;判断商是否为0,如果高低位高都为0,则返回,首先判断高16位
	  jcxz dwtoc2			;如果为0,则跳转到dtoc2,进行低位判断
	  jmp short dwtoc1       ;如果不为0,则跳转,继续进行除法运算
	  
dwtoc2:mov cx,ax             ;当高位为0时,判断低位
      jcxz dwtoc3            ;如果低位也为0,表明除法运算已完成,已经获取了所有的余数的ASCII码,就跳转到dtoc3处,进行写入操作
	  jmp short dwtoc1       ;如果不为0,则跳转,继续进行除法运算
	  
dwtoc3:pop cx                ;因为先前将cx入栈了,cx中保存的是余数的ASCII码,现在出栈
      mov ds:[si],cl		;cl保存的是余数,十进制
	  mov byte ptr ds:[si+1],2      ;mov byte ptr ds:[si+1],2  这句是给转换后字符赋颜色属性
      jcxz dwtoc4                    ;如果cx为0,则跳转到dtoc4处
      add si,2				;si+2是为下一个字符写入做准备

      jmp short dwtoc3		;如果cx不为0,则跳转到dtoc3处,继续写入字符
dwtoc4: mov byte ptr ds:[si],0			;最后,当所有字符写入完毕后在末尾加0
;      pop cx
 ;     mov si,0
      add di,0A0H			;先前di中存放的是将要写入的起始偏移地址,现在加上0A0H,表明是指向屏幕的下一行,也就是指向了与上一行所对应的字符处
	  mov si,di				;di中已经存放了要写入的下一行的地址,现在将di中的值放到si中,因为si将会用作下一次循环,用作写入地址
      ret	  
	  
divdw:mov bx,ax             ;将ax的值临时存放到bx中
      mov ax,dx             ;此时ax为高16位
      xor dx,dx
	  div cx             ;ax为商,dx为余数  rem(H/N)*1000H+L 
      push ax            ;高16位运算结果所得的商入栈
      mov ax,bx          ;此时ax为低16位	  
	  div cx             ;结果:ax存放低16位,dx存放高16位,cx存放余数
	  mov cx,dx          ;dx存放的是余数,现在将它给cx
	  pop dx			 ;第一次是进行高16位运算,现在将它还给dx,dx中存放的是高16位商
	  ret
	  
dtoc:mov cx,0			 ;cx为0入栈是为了下面的操作
     push cx
dtoc1:mov cx,10
      xor dx,dx
      div cx     		;L/N  	ax为商,dx为余
	  mov cx,dx    		;把余放入cx中
	  add cx,30H        ;现在cx+30为余数的ASCII码
	  push cx           ;保存余数的ASCII码进栈
	  mov cx,ax         ;将ax中的值放入cx中,判断ax的商
	  jcxz dtoc2        ;如果ax的商为零,表示各位余数都已经得到了,跳转至dtoc2处
	  jmp short dtoc1   ;如果商不为零,则跳转到dtoc1处继续进行除法运算,直到商为0止

dtoc2:pop cx
      mov ds:[si],cl
	  mov byte ptr ds:[si+1],2
	  jcxz dtoc3
	  add si,2
	  jmp short dtoc2

dtoc3:mov byte ptr ds:[si],0
      add di,0A0H
      mov si,di      
	  ret
codesg ends
end start

抱歉!评论已关闭.