实验二网络实验网络结构设计.docx
《实验二网络实验网络结构设计.docx》由会员分享,可在线阅读,更多相关《实验二网络实验网络结构设计.docx(15页珍藏版)》请在冰点文库上搜索。
实验二网络实验网络结构设计
网络设计之结构设计
课程设计
知识点:
(1)在子程序编写中,如果有修改寄存器的行为,要事先保护寄存器的原始值,并在使用完毕后再及时恢复寄存器。
(2)保护与恢复所采用的入栈push和出栈pop是成对出现的,并且入栈和出栈的顺序相反。
(3)调用子程序3步曲:
先准备好入口参数,再执行其功能,最后使用其返回值。
(4)内存的寻址方式的应用:
批量数据的传递。
任务:
将实验七中的Poweridea公司的数据,按照图10.2所示的格式在屏幕中显示出来。
程序结构设计(在实验报告中需用程序流程图来表达结构设计):
assumecs:
codesg
datasg1segment
db'1975',;原始数据:
参考实验七来填写
datasg1ends
tablesegment
db21dup('yearsummne?
?
');数据表,共有21行
tableends
datasg2segment
db16dup(0);以0结尾的字符串,用于写屏
datasg2
stacksgsegment
db64dup(0);自定义栈
stacksgends
;代码段
codesgsegment
start:
;
(1)段寄存器初始化ss:
sp
;
(2)原始数据到数据表
;为调用totable做准备:
ds指向datasg1段,es指向table段
movax,datasg1
movds,ax
movax,table
moves,ax
calltotable;调用totable子程序,原始数据数据表
;(3)请屏
callclearscreen
;(4)将table写屏
;初始化:
es:
bx指向table、ds:
si指向datasg2、循环控制参数cx、DOS窗口的行数dh
;es:
bxtable
movbx,0
;ds:
sidatasg2
movax,datasg2
movds,ax
movsi,0
cx=21;初始化cx计数器,一共显示21行
dh=3;从DOS窗口的第4行开始,show_str的入口参数
show_table:
;写屏
pushcx
;(i)显示年份
;table中的年份datasg2(字符串):
由于年份就是字符串,可以直接复制
movax,es:
[bx]
mov[si],ax
movax,es:
[bx+2]
mov[si+2],ax
movbyteptr[si+4],0;以0作为字符串结尾
;为调用show_str做准备:
movdl,2;从DOS窗口的第3列开始
movch,0;ch清零,防止高8位不为零。
movcl,2;字符颜色属性(二进制数00000010代表黑底绿字)
callshow_str;调用show_str子程序,显示以0结尾字符串
;(ii)显示总收入
pushdx
;为调用ddtoc做准备:
ax=?
、dx=?
callddtoc
popdx
;为调用show_str做准备:
dl=14
callshow_str
;(iii)显示雇员数
;为调用dtoc做准备:
movax,es:
[bx+10];将雇员数送入ax
calldtoc;将雇员数转换成字符串后写入datasg2段中
;为调用show_str做准备:
dl=30
callshow_str
;(iv)显示人均收入
;为调用dtoc做准备:
ax?
calldtoc
;为调用show_str做准备:
dl=44
callshow_str
;更新循环控制参数bx、dh
addbx,10H;bx指向下一行(table中一行有16字节)
incdh;累加dh(下一行显示)
popcx
loopshow_table
;主程序结束
movax,4c00H
int21H
;-------------------子程序-------------------
;
(1)totable
;
(2)clearscreen
;(3)show_str
;(4)dtoc
;(5)ddtoc
;(6)divdw
codesgends
endstart
子程序样本5例(totable、clearscreen、show_str、dtoc与divdw):
;------
;名称:
totable
;功能:
将数据段中的数据整理并写入表段中
;参数:
ds指向数据内存段入口、es指向表内存段入口
;返回:
无
;------
totable:
;将totable中所有需要使用的寄存器变量都保存起来。
pushax
pushds
pushes
pushbx
pushsi
pushdi
pushcx
;初始化偏移地址寄存器变量:
用bx定位年份和总收入(都是双字单元),
;用di定位人数(字单元),用si定位table中的每行(16个字节单元)
movbx,0
movsi,0
movdi,0
movcx,21;初始化计数器
torecord:
;写入年份
movax,0[bx];可以改成movax,[bx+0]
moves:
[si],0,ax
movax,2[bx]
moves:
[si].,ax
;写入空格
moval,20H
moves:
[si].4,al
;写入总收入
movax,84[bx]
moves:
[si].5,ax
movax,86[bx]
moves:
[si].7,ax
;写入空格
moval,20H
moves:
[si].9,al
;写入雇员数
movax,168[di]
moves:
[si].10,ax
;写入空格
moval,20H
moves:
[si].12,al
;除法后写入人均收入,高16位送入dx,低16位送入ax
movax,[bx+84]
movdx,[bx+86]
;除数使用bp变量
movbp,[di+168]
divbp
moves:
[si].13,ax
;写入空格
moval,20H
moves:
[si].15,al
;bx、si、di变量的递增
addbx,4;年份和总收入都是双字单元,故bx的递增量是4
adddi,2;人数是字单元,故di的递增量是2
addsi,16;table中每行是16个字节,偏移量为16
looptorecord
;恢复寄存器变量,并返回主调程序
popcx
popdi
popsi
popbx
popes
popds
popax
ret;totable结束
;------
;名称:
clearscreen
;功能:
DOS命令提示符窗口清屏,满黑屏显示
;参数:
无
;返回:
无
;------
clearscreen:
;将子程序用到的所有寄存器入栈保存
pushax
pushcx
pushes
pushdi
movax,0b800H
moves,ax;设置es:
di指向显示缓冲区内存段
movcx,2000;设置循环次数,屏幕是25行80列
movdi,0
screenclear:
movbyteptres:
[di+0],'';第一个字节写入空格
movbyteptres:
[di+1],0;第二个字节写入字符属性0(代表黑色)
adddi,2
loopscreenclear
;恢复寄存器
popdi
popes
popcx
popax
ret;clearscreen结束
;------
;名称:
show_str
;功能:
按指定的屏幕上的行和列位置,以及字符属性,显示以0结尾的字符串
;参数:
dh-行数(范围0-24)、dl-列数(范围0-79)、cl-字符属性、ds:
si指向字符串入口
;返回:
无
;------
show_str:
;将子程序用到的所有寄存器入栈
pushdx
pushcx
pushes
pushbx
pushsi
movax,0b800H;0b800H为命令窗口入口的显存地址
moves,ax;设置显示缓冲区内存段
movax,0;(ax)=0,防止高位不为零
moval,160;0a0H=160字节/行
muldh;相对于0b800:
0000的第dh行的偏移量
movbx,ax;将第(dh)行的偏移地址送入bx(如500H),代表行偏移
movax,0
moval,2;2个字节/字符
muldl;同一行列的偏移量,尽量使用乘法,(al)=6H为列偏移
addbx,ax;获得最终的偏移地址bx(如506H)
movdi,0;将di作为每个字符的偏移量
moval,cl;将字符属性写入al中
movch,0;将cx高8位设置为0
show_c:
movcl,[si];将字符串单个字符读入cl中
jcxzdone;判断字符串是否为零
moves:
[bx+di+0],cl;在显示缓冲区中写入字符
moves:
[bx+di+1],al;在显示缓冲区中写入字符属性
adddi,2
incsi
jmpshortshow_c
done:
;字符串的字符为0,结束
;恢复寄存器
popsi
popbx
popes
popcx
popdx
ret;show_str结束
;------
;名称:
dtoc
;功能:
将一个word型的数据转换成以0结尾的十进制字符串,并写入数据段中
;参数:
ax-word型数据、ds:
si指向字符串入口
;返回值:
无
;------
dtoc:
;保护寄存器变量值,因为下面的变量子程序都用到。
pushax
pushbx
pushcx
pushdx
pushsi
movsi,0;偏移地址置零
movbx,10;除数=10
getc4d:
movdx,0;涉及到16位除法,先将存储余数的寄存器置零
divbx;做除法(ax)/(bx)
movcx,ax;将除法运算结果的商赋值给cx,用于条件判断
jcxzlast4d;判断商cx是否为0?
adddx,30H;将一位数字转换成ASCII码
pushdx;将ASCII码入栈保存
incsi
jmpshortgetc4d
last4d:
;还需将最后一次除法的余数(dx)转换为ASCII码并入栈
adddx,30H;将数字转换成ASCII码
pushdx;将ASCII码入栈
incsi;最后一次也已转换并入栈
;将栈中字符倒序写入内存数据段中
movcx,si;(si)=字符串共几个字符,用来设置循环计数器cx。
movsi,0
write4d:
pop[si];出栈,并写入数据段。
incsi
loopwrite4d
movbyteptr[si],0;用0来结束字符串
;恢复寄存器,并返回主调程序。
popsi
popdx
popcx
popbx
popax
ret;dtoc结束
;------
;名称:
divdw
;功能:
进行不会产生溢出的16位除法运算
;参数:
ax-dword型被除数的低16位、dx-dword型被除数的高16位、cx-除数
;返回:
ax-dword型商的低16位、dx-dword型商的高16位、cx-余数
;------
divdw:
pushbx;暂存
pushax;将被除数低16位先入栈保存。
movax,dx;(ax)=(dx)
movdx,0000H
divcx;例子:
(dx)=0000H,(ax)=000FH,组合成0000000FH。
movbx,ax;将H/N的商先保存在bx中,例子:
(bx)=0001H。
注:
余数在dx中,例子:
(dx)=0005H
popax;将L值出栈到ax
divcx;例子:
(dx)=0005H,(ax)=4240H,组合成54240H
movcx,dx;返回值(cx)=最终的余数
movdx,bx;返回值(dx)=最终商的高16位值=(bx)。
注:
最终商的低16位在ax中
popbx;恢复
ret
待完成子程序ddtoc:
;------
;名称:
ddtoc
;功能:
将一个dword型数据转换成以0结尾的十进制字符串,并写入数据段中。
;参数:
ax-dword型数据的低16位、dx-dword型数据的高16位、ds:
si指向字符串入口
;返回值:
无
;------
ddtoc:
;ddtoc子程序开始
;将子程序所有用到的寄存器入栈
;ddtoc子程序内容
;恢复寄存器
?
?
?
ret;ddtoc子程序结束
程序流程图
子程序ddtoc:
dtoc:
push ax
push cx
push dx
push si
movcx,0
push cx ;先将0入栈,作为标记
dtc_s0:
movcx,ax
add cx,dx
jcxz dtc_s1
movcx,10
call farptr divdw
add cx,30h
push cx
loopdtc_s0
dtc_s1:
popcx
movds:
[si],cl
jcxz dtc_s2
inc si
loopdtc_s1 ;将栈中数据取出
dtc_s2:
pop si
pop dx
pop cx
pop ax
retf