Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1134|回复: 0

[默认分类] 汇编语言(王爽)实验十 编写子程序

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-6-27 10:40:22 | 显示全部楼层 |阅读模式
    标 题:
    汇编实验10—— 编写子程序

    作 者: XHS_12302
    时 间: 2016_7_28 16:56







    实验10编写子程序



      在这次实验中,我们将要编写3个子程序,通过它们来认识几个常见的问题和掌握解决这些问题的方法。同前面的所有实验一样,这个实验是必须要独立完成的,在后面的课程中,将要用到这个实验中编写的3个子程序。


    1.  显示字符串


    问题


    显示字符串是现实工作中经常要用到的功能,应该编写一个通用的子程序来实现这个功能。我们应该提供灵活的调用接口,使调用者可以决定显示的位置(行、列)、内容和颜色。




    提示


    (1)  子程序的入口参数是屏幕上的行号和列号,注意在子程序内部要将它们转化为显存中的地址,首先要分析一下屏幕上的行列位置和显存地址的对应关系:


    (2)  注意保存子程序中用到的相关寄存器:


    (3)  这个子程序的内部处理和显存的结构密切相关,但是向外提供了与显存结构无关的接口。通过调用这个子程序,进行字符串的显示时可以不必了解显存的结构,为编程提供了方便。在实验中,注意体会这种设计思想。



    子程序描述
    名称:show_str
    功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
    参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),
        (cl)=颜色,ds:si指向字符串的首地址
    返回:无
    就用举例:在屏幕的8行3列,用绿色显示data段中的字符串。





    代码:
    1. assume cs:code
    2.    data segment
    3.    db "Welcome to masm!",0
    4.    data ends
    5. code segment
    6.    start:  mov dh,8
    7.            mov dl,3
    8.            mov cl,2
    9.            mov ax,data
    10.            mov ds,ax
    11.            mov si,0
    12.           call show_str
    13.          mov ax,4c00h
    14.          int 21h
    15.    show_str: push dx
    16.              push cx
    17.              push ds
    18.              push si
    19.      mov ax,0b800h
    20.      mov es,ax
    21.      
    22.      mov al,160
    23.      mul dh
    24.      mov bx,ax
    25.      mov al,2
    26.      mul dl
    27.      add bx,ax
    28.     mov al,cl
    29.    
    30.          s: mov cl,[si]
    31.              jcxz ok
    32.                 mov dx,[si]
    33.               mov es:[bx],dx
    34.               mov es:[bx+1],al
    35.               inc si
    36.               add bx,2
    37.               loop s
    38. ok:            
    39.   pop si
    40.   pop ds
    41.   pop cx
    42.   pop dx
    43. ret
    44. code ends
    45. end start
    复制代码


    实验截图








    2.  解决除法溢出的问题
    问题
    前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数:进行16位除法的时候,用ax存储结果的商,dx存储结果的余数。可是,现在有一个问题,如果结果的商大于ah或ax所能存储的最大值,那么将如何?
    比如,下面的程序段:
    mov bh,1
    mov ax,1000
    div bh
    进行的是8位除法,结果的商为1000,而1000在ah中放不下,
    又比如,下面的程序段:
    mov ax,1000h
    mov dx,1
    mov bx,1
    div bx
    进行的是16位除法,结果的商为11000H,而11000H在ax中存放不下。
    我们在用div指令做除法的时候,很可能发生上面的情况:结果的商过大,超出了寄存器所能存储的范围。当CPU执行div等除法指令的时候。如果发生这样的情况,将引发CPU的一个内部错误。这个错误被称为:除法溢出。我们可以通过特殊的程序来处理这个错误, 这里我们不讨论这个错误的处理,这是后面的课程中要涉及的内容。

    好了,我们已经清楚了问题的所在:用div指令做除法的时候可能产生除法溢出。由于有这样的问题,在进行除法运算的时候要注意除数和被除数的值,比如1000000/10就不能用div指令来计算。那么怎么办呢?我们用下面的子程序divdw解决。


    子程序描述
    名称:divdw
    功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
    参数:(ax)=dword型数据的低16位
        (dx)=dword型数据的高16位
        (cx)=除数
    返回:(dx)=结果的高16位,(ax)=结果的低16位
        (cx)=余数
    应用举例:计算1000000/10(F4240H/0AH)
      mov ax,4240h
      mov v dx,000fh
      mov cx,0ah
      call divdw


    提示
    给出一个公式:
    X:被除数,范围:[0,FFFF FFFF]
    N:除数,范围:[0,FFFF]
    H:X高16位,范围:[0,FFFF]
    L:X低16位,范围:[0,FFFF]
    int():描述性运算符,取商,比如:rem(38/10)=8
    rem():描述性运算符,取答数,比如:rem(38/10)=8
    公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
    这个公式将可能产生溢出的除法运算:X/N,转变为多个不会产生溢出的除法运算。
    公式中,等号右边的所有除法运算都可以用div指令来做,肯定不会导致除法溢出。

    代码:
    1. assume cs:code
    2.     code segment
    3.     start:mov ax,4240h
    4.           mov dx,000fh
    5.           mov cx,0Ah
    6.           call divdw
    7.           mov ax,4c00H
    8.           int 21h
    9. divdw:
    10.       push ax
    11.       mov ax,dx
    12.       mov dx,0
    13.       div cx
    14.       mov bx,ax
    15.       pop ax
    16.       div cx
    17.       mov cx,dx
    18.       mov dx,bx
    19.       ret   
    20.     code ends
    21. end start
    复制代码



    程序截图:










    3.数值显示
    问题
    编程,将data段中的数据以十进制的形式显示出来。
    data segment
    dw 123,12666,1,8,3,38
    data ends
      这些数据在内存中都是二进制信息,标记了数值的大小。要把它们显示到屏幕上,成为我们能够读懂的信息,需要进行信息的转化。比如,数值12666,在机器中存储为二进制信息:0011000101111010B(317AH),计算机可以理解它。而我们要在显示器上读到可以理解的数值12666,我们看到的应该是一串字符:“12666”。由于 显卡遵循的是ASCII编码,为了让我们能在显示器上看到这串字符,它在机器中应以ASCII码的形式存储为:31H、32H、36H、36H、36H(字符“0”~“9”对应的ASCII码为30H~39H)。
      通过上面的分析可以看到,在概念世界中,有一个抽象的数据12666,它表示了一个数值的大小。在现实世界中它可以有多种表示形式,可以在电子机器中以高低电平(二进制)的形式存储,也可以在纸上、黑板上、屏幕上以人类的语言“12666”来书写。现在,我们面临的问题就是,要将同一抽象的数据,从一种表示形式转化为另一种表示形式。
      可见,要将数据用十进制形式显示到屏幕上,要进行两步工作:
    (1)  将用二进制信息存储的数据转变为十进制形式的字符串:
    (2)  显示十进制形式的字符串。
    第二步我们在本次实验的第一个子程序中已经实现,在这里只要调用一下show_str即可。我们来讨论第一步,因为将二进制信息转变为十进制形式的字符串也是经常要用到的功能,我们应该为它编写一个通用的子程序。


    子程序描述
    名称:dtoc
    功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
    参数:(ax)=word型数据
        ds:si指向字符串的首地址
    返回:无
    应用举例:编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。
    在显示时我们调用本次实验中的第一个子程序show-str。


    提示
      下面我们对这个问题进行一下简单地分析。
    (1)  要得到字符串“12666”,就是要得到一列表示该字符的ASCII码:31H、32H、36H、36H、36H。
    十进制数码字符对应的ASCII码=十进制数码值+30H
    要得到表示十进制数的字符串,先求十进制数每位的值。
    例:对于12666,先求得每位的值:1、2、6、6、6。再将这些数分别加上30H,便得到了表示12666的ASCII码串:31H、32H、36H、36H、36H。
    (2)  那么,怎样得到每位的值呢?采用如图10.2所示的方法。









      图10.2除10取余法示意
      





      可见,用10除12666,共除5次,记下每次的余数,就得到了每位的值。


    (3)  综合以上分析,可得出处理过程如下:


    用12666除以10,循环5次,记下每次的余数;将每次的余数分别加30H,便得到了表示十进制数的ASCII码串,如图10.3所示。





      




    图10.3得到十进制每位数字字符的方法示意





    (4)  对(3)的质疑:


    在已知数据是12666的情况下,知道进行5次循环。可在实际问题中,数据的值是多少


    程序员并不知道,也就是说,程序员不能事先确定循环次数。


      那么,如何确定数据各位的值已经全部求出了呢?我们可以看出,只要是除到商为0,各位的值就已经全部求出。可以使用jcxz指令来实现相关的功能。



    代码:
    1. assume cs:code
    2.   data segment
    3.    db 16 dup(0)
    4.   data ends
    5.   code segment
    6.     start:mov ax,12666
    7.           mov bx,data
    8.           mov ds,bx
    9.           mov si,0
    10.           call dtoc
    11.           mov dh,8
    12.           mov dl,3
    13.           mov cl,2
    14.           call show_str
    15.           mov ax,4c00h
    16.           int 21h
    17. dtoc:
    18.         mov cx,ax    ;17
    19.        jcxz bk
    20.          push ax
    21.        mov al,ah
    22.        mov ah,0
    23.        mov bl,10
    24.        div bl
    25.      mov cl,al
    26.      mov ch,ah
    27.        pop ax
    28.      mov ah,ch
    29.        div bl
    30.      mov dl,ah
    31.      mov dh,0
    32.       push dx
    33.        mov ah,cl
    34.      jmp short dtoc   ;29
    35.      bk:pop ax
    36.         add ax,30h
    37.         mov [si],al
    38.         
    39.         pop ax
    40.         add ax,30h
    41.         mov [si+1],al
    42.       
    43.         pop ax
    44.         add ax,30h
    45.         mov [si+2],al
    46.         
    47.         pop ax
    48.         add ax,30h
    49.         mov [si+3],al    ;44
    50.         
    51.         pop ax
    52.         add ax,30h
    53.         mov [si+4],al
    54.         mov byte ptr [si+5],0
    55.         ret
    56.       
    57.      
    58. show_str:
    59.             mov si,0
    60.      mov ax,0b800h
    61.      mov es,ax
    62.      
    63.      mov al,160
    64.      mul dh
    65.      mov bx,ax
    66.      mov al,2
    67.      mul dl
    68.      add bx,ax
    69.     mov al,cl
    70.    
    71.          s: mov cl,[si]
    72.              jcxz ok
    73.                 mov dx,[si]
    74.               mov es:[bx],dx
    75.               mov es:[bx+1],al
    76.               inc si
    77.               add bx,2
    78.               loop s
    79. ok: ret   
    80.   code ends
    81. end start
    复制代码

    程序运行截图




    至此    实验完成   
                               题中有不足之处  希望不吝赐教
                                             文中有的 文字是借鉴别人的    除了代码和截图
                                                 完成实验参考过别的资料,在第二个实验中受过小甲鱼视频(328/2)的启发
                                                                                                   视频资料上云盘找:链接: http://pan.baidu.com/s/1nvpQiLz 密码: et5r
                                                                                                                                                                                                                                     日期:2016_7_28
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-24 08:02 , Processed in 0.443683 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表