王爽汇编语言课程设计1

assume cs:code,ds:data,es:powerIdea

powerIdea 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'

        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
        dd 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
        dw 11542,14430,15257,17800
powerIdea ends

data segment
        db 11 dup ('0') ;用来存放10进制格式字符串,以‘0’结尾,由于double word型
                        ;数据转化成10进制字符串不会超过十位,再加上末尾的'0',共
                        ;11位,所以这里用11个字节存放
data ends

code segment
    start:call clear_screen ;先清屏
          mov ax,data   ;将ds:si指向data段第一个元素
          mov ds,ax
          sub si,si

          mov ax,powerIdea  ;将es:di指向powerIdea段第一个元素
          mov es,ax
          sub di,di

          sub bx,bx ;将bx清零,用来定位雇员数
          mov dh,1  ;dh为行号,将dh置1,程序执行后由于按下了回车,将出现在第0sub cx,cx ;将cx清零
          mov cl,02h    ;将02h赋给cl,show_str中cl用来决定字符串的颜色 
                        ;此处为绿色


          ;如果dh为22,则说明已经进行了21此循环,应结束程序
        l:push cx   ;保存cx   
          sub ch,ch ;将行号dh的值赋给cx,再用jcxz指令判别cx是否为22
          mov cl,dh ;若是则说明程序应当结束
          sub cx,22
          jcxz done
          pop cx    ;恢复cx


          mov ax,es:0[di]   ;将年份的头两个字节移动到ds:si处
          mov [si],ax
          mov ax,es:0[di+2] ;将年份的后两个字节移动到ds:si+2处
          mov [si+2],ax 
          mov byte ptr [si+4],0 ;末尾补0作为结束符,此时ds:si即有一个以零结尾的10进制形式字符串
          mov dl,2  ;dl决定ds:si处的字符串的列号
          call show_str ;行号(dh)、列号(dl)、颜色(cl)和字符串首地址都已确定
                        ;调用show_str即可在相应位置显示
          call clear    ;将ds:si处往后的11个字节清零,也可不进行此操作

          push dx   ;将dx压栈,因为后面需用到dx
          mov ax,es:84[di]  ;将收入的前两个字节送入ax作为要转化数据的低16位
          mov dx,es:84[di+2]    ;将收入的后两个字节送入dx作为要转化数据的高16位  
          call dtoc ;要转化的double word型数据以确定,目的地址ds:si也已确定,调用dtoc开始转化
          pop dx    ;恢复dx
          mov dl,12 ;设置字符串将在第12列显示
          call show_str ;显示字符串
          call clear    


          push dx   ;将dx压栈,因为后面需用到dx    
          mov dx,es:84[di+2]    ;由于前面只改变了dx而没有改变ax
                                ;所以此处重新将收入的后两个字节送入dx,使dx,ax表示收入
          push cx   ;将cx压栈,因为后面需用到cx
          mov cx,es:168[bx] ;将雇员人数送入cx设置除数,divdw的参数中cx表示除数,ax表示被除数低16位
                            ;dx表示被除数高16位
          call divdw    ;进行无溢出除法,结果为32位,ax存放低16位,dx存放高16pop cx    ;恢复cx
          call dtoc ;开始将(收入/雇员人数)的结果进行转化
          pop dx    ;恢复dx
          mov dl,32 ;设置字符串将显示在第32列
          call show_str;显示字符串
          call clear


          push dx   ;将dx压栈,因为后面需用到dx    
          mov ax,es:168[bx] ;准备转化雇员人数,用雇员人数设置ax,dx清零,
          sub dx,dx         
          call dtoc ;开始转化
          pop dx    ;恢复dx
          mov dl,22 ;设置雇员人数将显示在第22列
          call show_str ;显示字符串
          call clear

          add dh,1      ;行数递增
          add di,4      ;用于定位double word型数据的di加4
          add bx,2     ;用于定位word型数据的bx加2
        jmp short l

     done:pop cx    ;弹出执行jcxz done指令前压入的cx
          mov ax,4c00h
          int 21h



          ;名称:dtoc,需用到无溢出除法divdw
        ;功能:将double word型数据转化为表示一个十进制数的字符串,以0结尾
        ;参数:(ax)=dw型数据低16位,(dx)=dw型数据高16位,ds:si指向字符串首地址
        ;返回:无
         dtoc:push ax   ;将需要用到的寄存器压栈
              push cx
              push dx
              push si

              sub cx,cx ;0入栈,作为结尾字符0
              push cx       
              mov cx,0ah    ;设置除数
      dtoc_l0:call divdw    ;调用无溢出除法
              add cx,30h    ;将余数加30h得到十进制各位数值的ASCII码
              push cx   ;将得到的结果压栈
              push dx   ;将dx,ax压栈,保存商
              push ax
              or dx,ax  ;判断商是否为0,若是则转到dtoc_p处执行
              mov cx,dx
              jcxz dtoc_p
              pop ax    ;将商还原到ax,dx,
              pop dx
              mov cx,0ah    ;重新设置除数
              jmp short dtoc_l0 ;循环执行

       dtoc_p:pop ax    ;将最后保存的商(ax=0000,dx=0000)出栈
              pop dx
      dtoc_l1:pop ax    ;将栈中数据弹出到ax中
              mov [si],al   ;将数据低8位(十进制数各位数值+30H)送入目的地址
              mov cx,ax ;判断是否读到了0,若是则跳转到done0处执行
              jcxz dtoc_done    
              inc si ;si=si+1,循环执行
              jmp short dtoc_l1

    dtoc_done:pop si
              pop dx
              pop cx
              pop ax
              ret


            ;无溢出除法
            ;输入:ax:被除数低16位,dx:被除数高16位,cx:除数
            ;输出:ax:结果低16位,dx:结果高16位,cx:余数
            ;X:被除数,[0,ffffffff]
            ;N:除数,[0,ffff]
            ;H:X高16位,[0,ffff]
            ;L:X低16位,[0,ffff]
            ;int():取商
            ;rem():取余数
            ;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
       divdw: push bx   ;用到的寄存器入栈

      divdw_p:mov bx,ax     ;用bx保存被除数低16位(L)
              mov ax,dx     ;将被除数高16位(H)送入ax,准备进行除法运算(H/N)
              sub dx,dx     ;将dx清零
              div cx    ;高16位(H)除以除数
              push ax   ;将(H/N)的商压栈保存,作为最终结果的高16位
              mov ax,bx     ;将低16位(L)送入ax,连同(H/N)的余数(此时在dx中)一起除cx
              div cx
              mov cx,dx     ;最终商放在ax中,余数送入cx
              pop dx    ;将(H/N)的商送入dx作为结果的高16位

 divdw_done:  pop bx    ;用到的寄存器出栈
              ret




   ;名称:clear
   ;功能:将ds:si开始的11个字节的数据置零
   ;参数:ds:要归零数据的段地址;si:要归零数据的偏移地址
   ;返回:无
   clear:push cx    ;将要用到的寄存器入栈
         push si    
         mov cx,11  ;设置循环次数等于11
 clear_l:mov byte ptr [si],0    ;将ds:si置零
         inc si ;递增si
         loop clear_l   
    done:pop si ;恢复用到的寄存器值
         pop cx
         ret



                        ;在指定位置,用指定颜色,显示一个用0作为结束符的字符串
                ;参数:dh:行号;dl:列号;cl:颜色;ds:si指向字符串首地址
                ;返回:无
       show_str:push di     ;保存需用到的寄存器
                push dx
                push es
                push bx
                push cx
                push si
                push ax
     show_str_p:mov al,0a0h     ;dh*a0h+dl*02h即为相对于b8000的偏移
                mul dh  
                mov bx,ax   ;用bx保存dh*a0h的结果
                mov al,02h  
                mul dl  ;计算dl*02h
                add ax,bx   ;计算dh*a0h+dl*02h
                mov di,ax   ;将偏移地址送入di
                mov ax,0b800h   ;设置段地址,用es保存
                mov es,ax
                mov bl,cl   ;由于jcxz指令要用到cl,所以用bl来保存cl的值
     show_str_l:mov cl,[si]     ;用jcxz指令判断是否遇到0,如果是者跳转到done,结束程序
                mov ch,0
                jcxz show_str_done
                mov es:[di],cl  ;开始往目的地址处转移数据
                mov es:[di+1],bl    ;转移颜色数据
                inc si  ;源地址+1
                add di,2    ;目的地址+2
                jmp short show_str_l    ;跳转到l
  show_str_done:pop ax  ;恢复寄存器值
                pop si
                pop cx
                pop bx
                pop es
                pop dx
                pop di
                ret




;名称:clear_screen
;功能:清屏(80*25)
;参数:无
;返回:无
clear_screen:push ax    ;保存用到的寄存器
             push cx
             push ds
             push bx

             mov cx,07d0h   ;设置循环次数为2000
             mov ax,0b800h  ;设置显存段地址
             mov ds,ax  
             mov bx,0   ;偏移地址置为0
    clear_screen_l:mov word ptr [bx],0  ;设置要显示的内容为0000(黑色)
                   add bx,2 ;偏移地址加2
                   loop clear_screen_l  
    clear_screen_done:pop bx    ;恢复用到的寄存器值
                      pop ds
                      pop cx
                      pop ax
                      ret
code ends

end start
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值