汇编网首页登录博客注册
youthangel的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
文章收藏

[2012-10-12 15:12] 实验十

图片载入中
这个实验主要练习子程序的书写,重点把握现场保护与恢复、参数的传递和返回,相当于C中的函数
掌握了这些我们以后就可以写一些大程序了,比如贪吃蛇、俄罗斯方块啊等等
1、显示字符串
     comment            ;
实验十 第一题     
 编写显示子程序,在指定位置显示指定格式的字符串 


              assume    cs:code,ds:data
        data  segment
              db        'welcome to masm!',0
        data  ends
        code  segment
      start:
              mov       dh,8        ;行
              mov       dl,3        ;列
              mov       ax,data
              mov       ds,ax       ;数据来源
              mov       si,0        ;偏移量
              call      show_str
;暂停
              mov       ah,1
              int       21h
;退出 
              mov       ax,4c00h
              int       21h
              
     comment            ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列,字符显示属性 数据段的10h处 
返回:无      
;              
   show_str:
              push      di
              push      es
              push      ax          ;保护现场

              mov       al,160
              mul       dh         ;算出第8行在显存中的位置
              mov       di,ax
              add dl,dl
;算出第3列在第八行的第几个内存单元
              add       di,ax       ;算出显存的开始单元
              mov       ax,0b800h
              mov       es,ax       ;初始es
;开始显示    
          s:
              mov       al,[si]
              cmp       al,0
              je        return
              mov       es:[di],al
              mov       al,2
              mov       es:[di+1],al
              inc       si
              add       di,2
              jmp       s
;显示结束     
     return:
              pop       ax          ;回复现场
              pop       es
              pop       di
              ret
        code  ends
              end       start
2、解决除法溢出的问题
     comment            ;
 解决除法溢出的问题
1、计算出 
              mov       bh,1
              mov       ax,1000
              div       bh
的结果
2、计算出
              mov       ax,1000h
              mov       dx,1
              mov       bx,1
              div       bx
的结果  


              assume    cs:code
        code  segment
      start:
              mov       ax,1000h    ;被除数低八位
              mov       dx,1        ;被除数高八位
              mov       bx,1        ;除数
              call      divdw       ;32位的除法溢出
  
              mov       bh,1
              mov       ax,1000
              call      divw        ;16位的除法溢出
;退出
              mov       ax,4c00h
              int       21h


;------------------子程序 16位的除法溢出-------------------------- 
     comment            ;
 功能:解决16位除法溢出问题
参数:ax被除数,bh除数
返回:ax 商,bh余数  
;             
       divw:                        ;15位的除法溢出
;保护现场
              push      dx
;开始运算 
              mov       dl,al       ;保存低位
              mov       al,ah
              mov       ah,0
              div       bh          ;商在al中,余数在ah中
              mov       dh,al       ;保存高位商
              mov       al,dl       ;在次组成16位
              div       bh
              mov       bh,ah       ;余数放在bh中
              mov       ah,dh       ;商放在ax中
;运算结束,结果:商在ax中,余数在bh中 
              pop       dx
;恢复现场
              ret

              
 ;------------------子程序32位的除法溢出-------------------------- 
     comment            ;
 功能:解决32位除法溢出问题
参数:dx ax被除数,bx除数
返回:dx ax 商,cx余数  
;        
      divdw:                        ;32位的除法溢出
;保护现场
;开始运算 
              push      ax          ;把低位保存起来
              mov       ax,dx
              mov       dx,0
              div       bx          ;高八位的商在ax中,余数在dx中
              mov       cx,ax       ;把高位商给cx
              pop       ax          ;低位出栈
              div       bx          ;低位商在ax中,余数在dx中
              xchg      cx,dx       ;dx和cx中的数据交换
;运算结束,结果:商在dx:ax中,余数在cx中 
;恢复现场
              ret
        code  ends

              end       start
3、数值显示
     comment            ;
 将data段中的数据以十进制的形式显示在屏幕上
   算法分析:
1、数据在内存中是以十六进制的形式存储,先用连除取余将十六进制转换成十进制,暂存到栈里 
2、防止除法溢出需用到上一题的算法
3、指定位置显示用到第一题的算法
4、得到十进制数还要转换成去对应ASCII形式 
不足之处:
1、没必要每次都安除法溢出处理
2、结构化思想不够熟练
失误:
1、开始时,没有进行单元测试,写了一大坨代码,结果不能运行
2、模块之间的衔接(传参和返回)没能灵活把握,以致子程序返回出错
3、意志不坚定,当代码乱成一坨的时候,没耐心改完,以致耽误了一晚上的时间 

              assume    cs:code,ds:data,ss:stack
        data  segment
              dw        123,12666,1,8,3,38      ;要显示的原始数据
        data  ends
        temp  segment
              dw        8 dup(0)    ;数据暂存空间
        temp  ends
       stack  segment
              dw        8 dup(0)
       stack  ends
        code  segment
      start:
;es:di指向显存
;ds:si指向数据段
;ss:sp 指向栈段  
              mov       ax,stack
              mov       ss,ax
              mov       sp,10h      ;初始化栈
              mov       si,0
              mov       dh,8        ;行
              mov       dl,3        ;列
              mov       cx,6

          s:
;第一步 一个数转换成十进制数,每一位入栈,正好倒过来 
              mov       ax,data
              mov       ds,ax
              mov       ax,[si]     ;被除数
              mov       bp,0        ;初始化计数器bp,记录前的16进制数产生了多少个10进制数
         s0:
              mov       bx,10       ;除数,同时把bh置零
              call      divw        ;16位的除法溢出
              cmp       bl,0        ;判断是否除完
              je        c
              push      bx          ;每一个十进制数入栈
              inc       bp          ;记录个数
              jmp       s0
 ;第二步从栈中取出一个数的每一位转换成对应ASCII ,放入指定位置 
          c:
              mov       ax,temp
              mov       ds,ax
              mov       bx,0        ;规定指定位置ds:[bx]
         s2:
              pop       ax          ;从栈中取数据
              dec       bp          ;计数器减一
              mov       [bx],al     ;放到指定位置
              inc       bx          ;指向下一个指定位置
              cmp       bp,0        ;判断是否取完了
              jne       s2
              mov       al,0        ;结尾处放一个0,相当于C语言中字符串的结尾'\0'
              mov       [bx],al     ;结尾是 0
;第三步指定位置显示   
              mov       ax,temp
              mov       ds,ax       ;传参
              push      si          ;si入栈,方便指向临时存储段中数据
              mov       si,0        ;指向第一个字符
              call      show_str    ;显示字符
              pop       si          ;si出栈
              add       dl,8        ;列加8,相当于一个制表符
              add       si,2        ;si加二指向下一个字
              dec       cx          ;循环控制变量减一
              cmp       cx,0        ;检测循环次数
              jne       far ptr s   ;进入下一次循环
;暂停
              mov       ah,1
              int       21h
;退出
              mov       ax,4c00h
              int       21h
      

                   
;------------------子程序 16位的除法溢出-------------------------- 
     comment            ;
 功能:解决16位除法溢出问题
参数:ax被除数,bl除数
返回:ax 商,bh余数  
;             
       divw:                        ;15位的除法溢出
;保护现场
              push      dx
;开始运算 
              mov       dl,al       ;保存低位
              mov       al,ah
              mov       ah,0
              div       bl          ;商在al中,余数在ah中
              mov       dh,al       ;保存高位商
              mov       al,dl       ;在次组成16位
              div       bl
              mov       bl,ah       ;余数放在bh中
              mov       ah,dh       ;商放在ax中
;运算结束,结果:商在ax中,余数在bl中 
              pop       dx
;恢复现场
              ret

     comment            ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列 ,数据位置ds:si 
返回:无      
;              
   show_str:
              push      di
              push      es
              push      ax          ;保护现场

              mov       al,160
              mul       dh          ;算出第8行在显存中的位置
              mov       di,ax
              add dl,dl
;算出第3列在第八行的第几个内存单元
              add       di,ax       ;算出显存的开始单元
              mov       ax,0b800h
              mov       es,ax
;开始显示    
         s3:
              mov       al,[si]
              cmp       al,0
              je        return
              add       al,30h
              mov       es:[di],al  ;显示字符
              mov       al,2
              mov       es:[di+1],al
              inc       si
              add       di,2
              jmp       s3
;显示结束     
     return:
              pop       ax          ;回复现场
              pop       es
              pop       di
              ret
        code  ends

              end       start
评论次数(1)  |  浏览次数(274)  |  类型(汇编作业) |  收藏此文  | 

[  fpamc   发表于  2012-10-13 09:40  ]

不错~对于二倍的计算,用add自身相加或者shl左移一位也行,不需要mul。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码