首页 > 其他分享 ># 实验10

# 实验10

时间:2023-07-18 20:55:41浏览次数:36  
标签:10 16 mov cx 实验 dx ax bx

实验10

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

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

assume cs:code
data segment
db 'welcome to masm!',0
data ends

code segment
start:
mov dh,8
mov dl,3
mov cl,2
mov ax,data
mov ds,ax
mov si,0
call show_str

mov ax,4c00h
int 21h

show_str:
mov ax,0b800h
mov es,ax
mov al,160; 一行160个字节
dec dh
mul dh; 计算所在行数
mov dh,0; 因为dl存着列数,另一个加数一个字大小,故将dl变为一个字
push ax
mov ax,0
mov al,2
dec dl
mul dl; 计算所在列的下标
mov dx,ax
pop ax
add ax,dx; 相加得到开始所在下标
mov bx,ax; 将偏移地址传给bx
mov ah,cl; 将颜色传给ah。因为cx要存储循环次数
mov cx,16; 共16个字符
s:
push cx; 因为cx要用作判断,故先要保存cx的值
mov ch,0
mov cl,[si]
jcxz ok; 判断循环结束条件,当前字符是否为0
mov al,[si]
mov es:[bx],ax; 只需要将ax低位不断改变即可,因为颜色不变
add bx,2
inc si
pop cx
loop s
ok:
ret

code ends
end start
  1. 解决除法溢出的问题

前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数;进行16位除法的时候,用ax才能出结果的商,dx存储结果的余数,可是,现在有一个问题,如果结果的商大于alax所能存储的最大值,那么将如何?

比如下面的程序段:

Mov bh,1

Mov ax,1000

Div bh

进行的是8位除法,结果的商为1000,而1000al中放不下。

又比如,下面的程序段:

Mov ax,1000h

Mov dx,1

Mov bx,1

Div bx

进行的是16位除法,结果的商为11000h,而11000hal中放不下。

​ 我们在用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/10F4240H/0AH

Mov ax,4240h

Mov dx,000fh

Mov cx,0ah

Call divdw

​ 结果:dx=0001hax=86a0hcx=0

提示:

给出一个公式:

X:被除数,范围:[0ffffffff]

N:除数,范围:[0ffff]

H:X16位,范围:[0ffff]

L:X16位,范围:[0ffff]

Int():描述性运算符,取商,比如,int38/10=10

Rem():描述性运算符,取余数,比如,rem38/10=8

公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N

assume cs:code
code segment
start:
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw

mov ax,4c00h
int 21h

divdw:
mov bx,ax; bx寄存器空着,因为要做除法,会占用ax,故先将ax的值保存
mov ax,dx; 要做高位除法,将被除数先存进ax中
mov dx,0; dx清零,保存余数
div cx; 进行(H/N)
push ax; 将商的高16位保存,因为还有一次除法,dx正好可以直接用到,因为*65536相当于左移16位,低16位加上L正好组成被除数
mov ax,bx; bx就是低16位
div cx
mov cx,dx; dx存的余数,赋值给cx
pop dx; dx存的商高16位
; ax正好已经存了商的低16位
ret; 返回


code ends
end start
  1. 问题:
    编程,将data段中的数据以十进制的形式显示出来。
    data segment
    dw 123,12666,1,8,3,38
    data ends

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

assume cs:code

data segment
db 10 dup(0)
data ends

code segment
start:
mov ax,12666
mov bx,data
mov ds,bx
mov si,0
mov bx,0
call dtoc

mov dh,8
mov dl,3
mov cl,2
call show_str

mov ax,4c00h
int 21h

dtoc:
mov dx,0; 除法dx保存高16位,必须清零,不然程序会出错,具体表现为不知道会跳转到哪里
mov cx,10; 除数
div cx
add dx,30h; 存该数字代表的ASCII码
mov [bx],dx; 存进data段中
mov cx,ax; 判断商是否为0,需要借助cx判断
add bx,2; 因为商是一个字大小,所以要加2个字节
inc si; 存一共多少位
jcxz ok
jmp dtoc

show_str:
mov cx,si; si存着数字一共多少位
mov di,cx; 因为要进行两次循环,si后面会用到,所以用di存
mov al,dh; 做乘法,获得该行所在的下标
dec al
mov ah,160
mul ah
mov bx,ax
mov al,dl; 做乘法,获得列所在的下标
mov ah,2
mul ah
add bx,ax; 行加列,获得下标
mov ax,0b800h; 显存段号
mov es,ax
mov si,0; 存储data段偏移量

s1:; 因为data段的结果与实际结果相反,故可以存入栈中再输出,得到正确的顺序
mov al,[si]
mov ah,2; 组合,低位ASCII码,高位颜色
push ax
add si,2
loop s1

mov cx,di; 将数字的位数传给cx
s2:
pop ax
mov es:[bx],ax; 赋值给显存,bx存着之前算得的下标
add bx,2
loop s2
ret

ok:
ret

code ends
end start

标签:10,16,mov,cx,实验,dx,ax,bx
From: https://www.cnblogs.com/alphadoiy/p/17564113.html

相关文章

  • AtCoder Beginner Contest 310
    A-OrderSomethingElse#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongint32_tmain(){ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);intn,p,q;cin>>n>>p>>q;......
  • hdu 1010 Tempter of the Bone (dfs+奇偶剪枝)
    小记:最开始以为是T时间内,用bfsWA了,后来知道是刚好T时间,然后就用dfs,相当于暴力了,然后简单的dfs提交TLE,必须剪枝。首先判最少需要的时间是否有,没有就不用继续了,而如果有,那么因为我们是要花掉T时间刚好到达,那么我们先保证能走到终点的时间,然后在路上花掉多余的时间此时,我们必须保证......
  • POJ 1410 Intersection
    判断线段与多边形是否相交。模板:#include<stdio.h>#include<math.h>#include<algorithm>usingnamespacestd;#definePi3.14159265358979#definePRECISION1e-8//点typedefstruct{doublex,y;}POINT;//直线两点的表达structLINE{POINTp1,p2;};......
  • 2014 蓝桥杯 预赛 c/c++ 本科B组 第八题:蚂蚁感冒(10')(4.9更新)
    第八题:蚂蚁感冒(10')  长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。   每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。  当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。  这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把......
  • Databend 开源周报第 102 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。为指定列创建BloomIndex创建bloomindex将会消耗大......
  • 8-102-(LeetCode- 207&210) 课程表
    1.题目 读题  考查点 2.解法思路这个问题可以用图论的方法来解决,具体思路如下:将课程和先修课程看作有向图的节点和边,如果要学习课程ai,则必须先学习课程bi,表示为bi->ai。判断图中是否存在环,如果存在环,则说明有些课程无法完成,返回false;如果不存在环,则说明所有课程都......
  • FX110讯:ADSS正逐步关闭英国业务
    总部位于阿布扎比的零售和机构货币对及差价合约经纪商ADSS将逐步关闭其英国业务——ADSSecuritiesLondonLtd(ADSSL),以便将资源重新集中于集团内的其他实体。去年10月,Fazzaco报告称,在截至2021年12月31日的2021财年,ADSSL的收入(不包括转让定价)同比下降了34%。就在本月初,DanBenton在A......
  • leetcode104二叉树搜索
    深度优先搜索,递归maxDepth(TreeNode*root){if(!root)return0;returnmax(maxDepth(root->left),maxDepth(root->right))+1;} 广度优先搜索,队列queue<TreeNode*>q;q.push(root);while(!q.empty()){intsize=q.size();while(size>0){Tree......
  • ABS10-ASEMI迷你贴片整流桥50MIL芯片ABS10
    编辑:llABS10-ASEMI迷你贴片整流桥50MIL芯片ABS10型号:ABS10品牌:ASEMI芯片个数:4封装:MBS-4恢复时间:ns工作温度:-55°C~150°C浪涌电流:30A正向电流:1A反向耐压:1000V正向压降:1.05V引脚数量:4漏电流:>10uaABS10特性:ASEMI品牌ABS10是采用GPP工艺芯片,该芯片具有良好的稳定性及抗......
  • win10小狼毫配置实操笔记
    下载安装进入官方网站下载最新版小狼毫,安装后选择朙(明)月拼音。在配置前阅读官方文档有关用户文件夹和共享文件夹的介绍。default.yaml用来调试全局方案,定制该文件后切换其他比如五笔、双拼等方案时,其定制内容依旧适用。weasel.yaml用来修改rime的常规设置,定制外观。symbol......