汇编实验三.docx
《汇编实验三.docx》由会员分享,可在线阅读,更多相关《汇编实验三.docx(20页珍藏版)》请在冰豆网上搜索。
汇编实验三
汇编语言程序设计
实验三汇编语言程序调试运行
学号:
姓名:
(1)将下面的数据段输入,取名为1.asm,保存在MASM文件夹下,生成.lst文件,不必连接运行,查看1.lst文件,试回答:
DA1,DA2的偏移量分别为多少?
COUNT的值为多少?
datasegment
org20h
num1=8
num2=num1+10h
da1db'IBMPC'
da2db0ah,0dh
countequ$-da1
dataends
end
DA1偏移量为20,DA2偏移量为26,count值为8
(2)输入下列指令,改正可能的错误(先不要运行程序):
datasegment
var1db0,25,0DH,30
var2db12h,0a4h,6bh
var3db'ABCDEF'
var4dw1234h,5678h
var5dw10hdup(?
)
dataends
codesegment
assumecs:
code,ds:
data
beginmovax,data
movds,ax
leasi,var5
movbx,offsetvar2
mov[si],0abh
movax,var1+2
mov[bx],[si]
movvar5+4,var4
movah,4ch
int21h
codeends
endstart
正确代码:
datasegment
var1db0,25,0DH,255
var2db12h,04h,6bh
var3db'ABCDEF'
var4dw1234h,5678h
var5dw10hdup(?
)
dataends
codesegment
assumecs:
code,ds:
data
start:
movax,data
movds,ax
leasi,var5
movbx,offsetvar2
movax,0abh
mov[si],ax
moval,var1+2
movax,[si]
mov[bx],ax
movax,var4
movvar5+4,ax
movah,4ch
int21h
codeends
endstart
(3)写一个完整的程序放在代码段C_SEG中,要求把数据段D_SEG中的AGUEND和附加段E_SEG中的ADDEND相加,并把结果存放在D_SEG中的SUM中。
其中AUGEND,ADDEND,SUM均为dw类型,AUGEND赋值为9251,ADDEND赋值为-5962。
实验报告中要求写出源程序,简单叙述上机步骤,调试方法。
a.实验步骤:
1.将AGUEND、AGUEND+2分别存入AX,DX中。
2.与ADDEND、ADDEND+2相加后,将相加后的结果存入SUM、SUM+2中。
3.以十六进制的形式显示结果。
b.源程序:
datassegment
augenddd9251
sumdd?
datasends
e_segsegment
addenddd-5962
e_segends
codessegment
assumecs:
codes,ds:
datas,es:
e_seg
start:
movax,datas
movds,ax
movax,e_seg
moves,ax
movax,wordptr[augend]
addax,wordptres:
[addend]
movdx,wordptr[augend+2]
adcdx,wordptres:
[addend+2]
movwordptr[sum],ax
movwordptr[sum+2],dx
movbx,wordptr[sum+2]
movch,4
movdh,1
AA:
movcl,4
rolbx,cl
moval,bl
andal,0fh
addal,30h
cmpal,3ah
jlprint
addal,07h
print:
movdl,al
movah,2
int21h
decch
jnzaa
movbx,wordptr[sum]
movch,4
decdh
jzaa
movah,4ch
int21h
codesends
endstart
c.显示结果:
(4)数组中是一组无符号数,将最小数放在M单元中,经过汇编后,形成.EXE文件,先用G=0命令执行程序,用-D命令查看M单元的内容,会发现结果不正确。
用单步执行命令T查找程序中的逻辑错误。
DSEGSEGMENT
MSGDB13,15,7,25,24
MDB?
DSEGENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
MOVCX,4
MOVAL,MSG
MOVSI,OFFSETMSG+1
L1:
CMPAL,[SI]
JBNEXT
MOVAL,[SI]
NEXT:
LOOPL1
MOVM,AL
MOVAX,4C00H
INT21H
CSEGENDS
ENDSTART
1.程序说明:
此程序的目的是要在13,15,7,25,24中找到最小数,并放在M单元。
2.调试说明:
运行无问题
3.错误问题:
结果中M单元的内容是错的,此时M为13,但真实值应为6.
4.解决方法:
该程序的循环是一个死循环,无法将每个数都进行比较,因此,需要每次循环时地址+1才能将每个数进行比较,所以需要在循环上加“INCSI”
5.修改后程序
DSEGSEGMENT
MSGDB13,15,7,25,24
MDB?
DSEGENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
MOVCX,4
MOVAL,MSG
MOVSI,OFFSETMSG+1
L1:
CMPAL,[SI]
JBNEXT
MOVAL,[SI]
NEXT:
INCSI
LOOPL1
MOVM,AL
MOVAX,4C00H
INT21H
CSEGENDS
ENDSTART
6.修改后运行结果:
(5)试编制一个汇编语言程序,求出首地址为DATA的10个无符号字数组中的最小偶数,把它存放在AX中。
画出程序框图,写出源程序清单和执行结果。
Dataword0141H,0AE00H,07B4H,0A508H,0691H,
word0870H,7542H,0081H,0916H,0017H
a.设计思路:
本程序需要在10个无符号数中寻找最小的偶数,关键点为最小和偶数,所以需要两次判断,最后把结果放在AX中。
b.程序设计图:
c.程序说明
dsegsegment
datadw0141H,0AE00H,07B4H,0A508H,0691H,0870H,7542H,0081H,0916H,0017H
dsegends
csegsegment
assumeds:
dseg,cs:
cseg
start:
movax,dseg
movds,ax
movcx,9//循环次数为9
movax,data//取data的首地址放在ax中
movsi,offsetdata+2//取data的第二号地址放在si中
L1:
testax,01h//判断ax中的数是奇数还是偶数
jnzL2//不等于0即为奇数,跳到L2地址
testwordptr[si],01h//判断[si]中的数是奇数还是偶数
jnznext//奇数跳到next地址
cmpax,[si]//比较ax与[si]
jbnext//ax小于[si],跳到next地址
L2:
movax,[si]//ax与[si]进行交换
next:
addsi,2//si+2,取下个数地址
LoopL1//L1进行循环
movax,4c00h//退出
int21h
csegends
endstart
d.程序结果:
(6)有10个数,统计正数的个数,存放在变量M中。
经过汇编后,形成.EXE文件,先用G=0命令执行程序,用-D命令查看M单元的内容,会发现结果不正确。
用单步执行命令T查找程序中的逻辑错误,注意每一次循环中AL寄存器中的值变化是否正确(AL寄存器中存放正数的个数)
DSEGSEGMENT
MSGDB4,-2,-6,0,5,67,8,-3,5,6
MDB?
DSEGENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
MOVCX,10
MOVAL,0
LEASI,MSG
L1:
MOVBL,[SI]
CMPBL,0
JBENEXT
INCAL
NEXT:
INCSI
LOOPL1
MOVM,AL
MOVAX,4C00H
INT21H
CSEGENDS
ENDSTART
a.程序说说明
这个程序的目的是要在4,-2,-6,0,5,67,8,-3,5,6中找出正数的个数。
b.调试说明:
运行无问题。
c.错误问题:
M单元中的内容错误,此时M为9,但真实值应为6.
b.程序代码:
dsegsegment
msgdb5,-4,0,3,100,-51
resultdb6dup(?
)
dsegends
csegsegment
assumecs:
cseg,ds:
dseg
start:
movax,dseg
movds,ax
movcx,6//循环6次
leasi,msg//取msg的首地址放在si中
leadi,result//取result的首地址放在result中
l1:
movbl,[si]//把si的内容放入bl中
cmpbl,0//比较bl与0的大小
jll3//bl小于0,跳到L3地址
cmpbl,0//比较bl与0的大小
jgl4//bl大于0,跳到L4地址
movbl,0//bl等于0
mov[di],bl//把bl的内容放在[di]中
jmpl2//跳到L2中
l3:
movbl,-1//bl=-1
mov[di],bl//把bl的内容放在[di]中
jmpl2//跳到L2中
l4:
movbl,1//bl=1
mov[di],bl//把bl的内容放在[di]中
l2:
incsi//si+1
incdi//di+1
deccx//cx-1
cmpcx,0
jzdonejmpl1
done:
movah,4ch
int21h
csejends
endstart
c.运行结果:
(8)数据段中的三个字符,调用子程序将其逐个显示出来。
子程序的功能是显示一个字符。
单步执行,观察SP、IP的变化,并用D命令查看栈顶的内容。
DATASEGMENT
MAGDB'ABC'
DATAENDS
STACK_SEGSEGMENT
DB100DUP(?
)
TOSLABELWORD
STACK_SEGENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK_SEG
START:
MOVAX,STACK_SEG
MOVSS,AX
MOVSP,OFFSETTOS
MOVAX,DATA
MOVDS,AX
MOVSI,0
MOVCX,3
LL:
MOVDL,MAG[SI]
CALLMADD
INCSI
LOOPLL
MOVAx,4C00H
INT21H
MADDPROC
MOVAH,02H
INT21H
RET
MADDENDP
CODEENDS
ENDSTART
a.单步执行程序,如下:
从图中可以看出,在执行call命令前,SP一直保持0064不变而IP持续增加。
在RET前从上图中可以看出,当程序在SP、IP每次都是分别按2和1递增,当运行到RET时,SP还是按照2来递增,而IP缺减少了,说明指针回撤执行下一个循环。
上图为用d命令查看栈顶内容
程序执行结果:
(9)将一个给定的二进制数按位转换成相应的ASCII码字符串,送到指定的存储单元,如二进制数10010011转换成字符串为‘10010011’。
要求将转换过程写成子程序,且子程序应具有较好的通用性,而必须能实现对8位和16位二进制数的转换。
(用寄存器或变量实现参数传递)
测试数据:
Var8bitbyte10010011B
Var16bitword
显示单元:
Show8bitbyte8dup(?
)
Show16bitbyte16dup(?
)
程序代码:
datasegment
Var8bitdb93h
Var16bitdw0a3c4h
Show8bitdb8dup(?
)
Show16bitdb16dup(?
)
dataends
codesegment
assumecs:
code,ds:
data
mainproc
start:
movax,data
movds,ax
movdl,Var8bit;二进制数传给DX
movcx,8;置位数8
leasi,Show8bit;字符串首址si
callbtrascii;调用子程序
mov[si],byteptr0dh;回车
mov[si+1],byteptr0ah;换行
mov[si+2],byteptr'$';结束符
leadx,Show8bit
movah,9h;打印字符串
int21h
movdx,Var16bit
movcx,16
leasi,Show16bit
callbtrascii
mov[si],byteptr0dh
mov[si+1],byteptr0ah
mov[si+2],byteptr'$'
leadx,Show16bit
movah,9h
int21h
movah,4ch
int21h
mainendp
btrasciiproc
cmpcx,8;看cx是否为8
jnel1
movdh,dl;将8位二进制数移到dx高8位
l1:
moval,0
roldx,1;dx左循环一次,将当前最高位给CF
rclal,1;al带进位左循环一次,得到CF,即dx最高位
addal,30h;将此位数转换成ascii码
mov[si],al
incsi
loopl1;循环cx次
ret
btrasciiendp
codeends
endstart
(10)将一个给定的二进制数按位转换成相应的ASCII码字符串,送到指定的存储单元,如二进制数10010011转换成字符串为‘10010011’。
要求将转换过程写成子程序,且子程序应具有较好的通用性,而必须能实现对8位和16位二进制数的转换。
(用堆栈实现传参:
可以选择用子过程来平衡堆栈,也可以用调用过程来实现平衡堆栈,程序功能说明中要指出)
测试数据:
Var8bitbyte10010011B
Var16bitword
显示单元:
Show8bitbyte8dup(?
)
Show16bitbyte16dup(?
)
程序代码:
datasegment
Var8bitdb93h
Var16bitdw0a3c4h
Show8bitdb8dup(?
)
Show16bitdb16dup(?
)
dataends
stacksegment
dw20dup(?
)
toslabelword;设置栈底,有无都可
stackends
codesegment
assumecs:
code,ds:
data,ss:
stack
mainproc
start:
movax,stack
movss,ax
movsp,offsettos
movax,data
movds,ax
movax,offsetVar8bit
pushax
movax,8;置位数8
pushax
movax,offsetShow8bit;字符串首址
pushax
callbtrascii
leadx,Show8bit
movah,9h
int21h
movax,offsetVar16bit
pushax
movax,16;置位数8
pushax
movax,offsetShow16bit;字符串首址
pushax
callbtrascii
leadx,Show16bit
movah,9h
int21h
movah,4ch
int21h
mainendp
btrasciiproc
pushbp
movbp,sp
pushbx
pushcx
pushsi
movsi,[bp+8];二进制数
movbx,[si]
movcx,[bp+6];位数
movsi,[bp+4];目标地址
cmpcx,8
jnelabel1
movbh,bl
label1:
moval,0
rolbx,1;bx左循环一次,将当前最高位给CF
rclal,1;al带进位左循环一次,得到CF,即dx最高位
addal,30h;将此位数转换成ascii码
mov[si],al
incsi
looplabel1;循环cx次
mov[si],byteptr0dh;回车
mov[si+1],byteptr0ah;换行
mov[si+2],byteptr'$'
popsi
popcx
popbx
popbp
ret
btrasciiendp
codeends
endstart
运行结果: