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

我的博客

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

[2023-08-14 18:42] 第 14 章 检测点 14.2

检测点 14.2

编程,用加法和移位指令计算 (ax)=(ax)*10。提示,(ax)*10=(ax)*2+(ax)*8。

具体代码如下:

1. 说明:AX 寄存器存储的初始数据不得超过 6553,因为 6553×10=65530 是 16 位寄存器 AX 能进行乘 10 计算后所存储的最大值,超过后就会由于 AX 寄存器的存储容量不足而导致溢出,所得的结果将是错误的。例如若计算 6554×10,结果为 65540,该数值在 AX 寄存器中实际存储的是其补码,即十进制的数值 4,因为 AX 寄存器最大能存储的无符号数为 65535。本程序代码只有计算功能,需通过 Debug 运行才能观察计算结果。

assume cs:code

code segment

start:  ; 计算 (ax)×10
        mov bx,53
        mov ax,bx
        mov cl,1
        shl ax,cl
        mov cl,3
        shl bx,cl
        add ax,bx  ; 计算的最终结果存储在 AX 寄存器中

        mov ax,4c00h
        int 21h

code ends

end start

2. 说明:AX 寄存器存储的初始数据不得超过 6553,因为 6553×10=65530 是 16 位寄存器 AX 能进行乘 10 计算后所存储的最大值,超过后就会由于 AX 寄存器的存储容量不足而导致溢出,所得的结果将是错误的。例如,若计算 6554×10,结果为 65540,该数值在 AX 寄存器中实际存储的是其补码,即十进制的数值 4,因为 AX 寄存器最大能存储的无符号数为 65535。本程序代码既有计算功能,也有在屏幕显示计算结果的功能。

assume cs:code

data segment
  db "6553 x 10 = ",0
data ends

; 由于 16 位寄存器 AX 能存储的最大无符号数是 65535,这是个 5 位数字,所以用于存储 5 位十进制数字的字符串空间只需 6 个字节(其中最后一个字节用于存储字符串结束符 0)。
stda segment
  db 6 dup (0)
stda ends

code segment

start:  mov ax,data
    mov ds,ax
    mov si,0  ; 令 ds:si 指向 data 段字符串的首地址
    mov bx,2  ; (bh)=0,设置显示缓冲区第 0 页;(bl)=2,设置字符属性为绿色
    mov dh,5  ; 在 BH 寄存器中存放行号
    mov dl,12  ; 在 DL 寄存器中存放列号
    call show

    ; 计算 (ax)×10
    mov bx,6553
    mov ax,bx
    mov cl,1
    shl ax,cl
    mov cl,3
    shl bx,cl
    add ax,bx  ; 计算的最终结果存储在 AX 寄存器中

; 转换 AX 寄存器中存储的数值数据为数字字符,并存入 stda 段中。
    mov bx,stda
    mov ds,bx
    mov si,0  ; 令 ds:si 指向 stda 段字符串的首地址
    call dtoc

    mov si,0  ; 重置 SI 寄存器存储 0 值,以令 ds:si 指向 stda 段字符串的首地址
    mov bx,2  ; (bh)=0,设置显示缓冲区第 0 页;(bl)=2,设置字符属性为绿色
    call show

    mov ax,4c00h
    int 21h

; begin show
; show 子程序:通过调用 BIOS 的 int 10h 指令中断例程的 2 号和 9 号子程序,在屏幕输出计算结果
show:  mov ah,2  ; 设置 int 10h 指令中断例程的子程序号为 2,功能为“设置光标位置”
    int 10h

    mov ah,9  ; 设置 int 10h 指令中断例程的子程序号为 9,功能为“在光标位置显示字符”
    mov al,[si]  ; 字符
    cmp al,0
    je showret  ; 判断当前需要显示的字符是否为字符串的结束符 —— ASCII 码值为 0
    mov cx,1  ; 字符重复个数
    int 10h
    inc si  ; ds:si 指向下一个字符
    inc dl  ; 列数自增 1,在下一列输出字符
    jmp short show
showret:  ret
; end show

; begin dtoc
; 参数:(ax) = 数值数据的低 16 位  (dx) = 数值数据的高 16 位  (cx) = 转换用到的除数值 10  ds:si 指向字符串首地址
; 功能:将提供的数值参数(被除数)转换为字符数字字符串形式,并将转换后的数字字符串存储到 ds:si 指向的段字符串中。
; 说明:转换成的字符数字字符串表示的如果是 10 进制数字,则提供的 (cx) 参数为十进制数值 10;如果是 8 进制数字,则 (cx) 参数为十进制数值 8;如果是 2 进制数字,则 (cx) 为十进制数值 2;如果是 16 进制数字,则 (cx) 为十进制数值 16。
dtoc:  push dx  ; 将显示字符串的屏幕行、列信息压入栈中
    mov dx,0  ; 设置高 16 位被除数 0,并存入 DX 寄存器 —— 低 16 位则在 AX 寄存器中
    push dx  ; 将数值 0 压栈,以作为 ok 标号处进行原序复制数字字符串的末尾结束符,以界定数字字符串的长度。在本子程序的 over 标号处将会通过 pop 操作将该 0 值出栈到 CX 寄存器

mca:  cmp ax,0  ; 判断被除数的低 16 位值是否为 0
    je mcd  ; 如果为 0,则跳至标号 mcd 处,以对高 16 位值是否为 0 作进一步判断;如果不为 0,则跳至 cd 标号处调用 divdw 子程序

cd:  mov cx,10  ; 设置求余时要用到的除数数值 10,并存入 CX 寄存器
    call divdw  ; 调用 divdw 子程序,解决“除法溢出”问题,并获得存储在 CX 寄存器的余数
    add cx,30h  ; 将数值转换为字符
    push cx  ; 将数值的数字字符压栈
    jmp mca  ; 跳至 mca 标号处,对下一轮除法运算的被除数进行是否为 0 的判断

mcd:  cmp dx,0  ; 判断被除数的高 16 位值是否为 0
    je over  ; 如果为 0,则跳至 over 标号处,以恢复数字字符串正常顺序;如果不为 0,则通过其后的 jmp 指令跳至 cd 标号处,调用 divdw 子程序
    jmp cd

over:  ; 将倒序显示的数字字符串恢复为原来数值的数字字符串正常序列
    pop cx  ; 将数值的数字字符出栈存入 CX 寄存器
    jcxz ok  ; 如果出栈字符的码值为 0,则说明数值的数字字符串已全部出栈完毕,应该跳至 ok 标号处返回主调程序
    mov [si],cl  ; 将 CL 寄存器中存储的字符转存入目标位置 ds:si;注意,不是 CX 寄存器
    inc si  ; si 后移 1 位,指向 stda 段下一个字符的存储位置
    jmp over; 跳至 over 标号处继续出栈操作,再次判断出栈字符的 ASCII 码值是否为 0

ok:  pop dx
    ret
; end dtoc

; begin divdw
; 参数:(ax) = 被除数的低 16 位  (dx) = 被除数的高 16 位 
 (cx) = 除数
; 返回:(ax) = 商数的低 16 位  (dx) = 商数的高 16 位 
 (cx) = 余数
divdw:  ; 执行高 16 位被除数与 16 位除数的除法运算
    mov bx,ax  ; 将被除数的低 16 位暂存到 BX 寄存器
    mov ax,dx  ; 将被除数的高 16 位转存到 AX 寄存器
    mov dx,0    ; 设置原被除数高 16 位进行的除法运算所需要使用的高 16 位被除数
    div cx  ; 执行高 16 位除法运算,计算结果的余数默认存储于 DX 寄存器
    push ax  ; 将高 16 位除法运算所得的商数入栈存储,将由下面的 pop dx 指令出栈转存
; 执行低 16 位被除数与 16 位除数的除法运算
    mov ax,bx  ; 将被除数的低 16 位传送回 AX 寄存器
    div cx  ; 执行低 16 位除法运算,计算结果的商数默认存储于 AX 寄存器
    mov cx,dx  ; 将低 16 位除法运算所得余数(也是最终除法运算的余数)转存到 CX 寄存器
  pop dx  ; 将高 16 位除法运算所得的商数出栈转存到 DX 寄存器
; 经 divdw 子程序上述操作后,AX、DX 和 CX 寄存器分别存储着商数的低 16 位、高 16 位和余数
    ret
; end divdw

code ends

end start
评论次数(0)  |  浏览次数(400)  |  类型(汇编作业) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码