最新1632位微机原理汇编语言及接口技术第二版第三章课后习题答案Word格式.docx
《最新1632位微机原理汇编语言及接口技术第二版第三章课后习题答案Word格式.docx》由会员分享,可在线阅读,更多相关《最新1632位微机原理汇编语言及接口技术第二版第三章课后习题答案Word格式.docx(27页珍藏版)》请在冰豆网上搜索。
assumecs:
code,ds:
data,ss:
stack
start:
movdx,offsetstring
movah,9
int21h
codeends
endstart
3.7DOS支持哪两种可执行程序结构,编写这两种程序时需要注意什么?
(1).EXE程序
程序可以有多个代码段和多个数据段,程序长度可以超过64KB
通常生成EXE结构的可执行程序
(2).COM程序
只有一个逻辑段,程序长度不超过64KB
需要满足一定条件才能生成COM结构的可执行程序(MASM6.x需要采用TINY模式)
3.8举例说明等价“EUQ”伪指令和等号“=”伪指令的用途
符号定义伪指令有“等价EQU”和“等号=”:
符号名EQU数值表达式
符号名EQU<
字符串>
符号名=数值表达式
EQU用于数值等价时不能重复定义符号名,但“=”允许有重复赋值。
例如:
X=7;
等效于:
Xequ7
X=X+5;
“XEQUX+5”是错误的
3.9给出下列语句中,指令立即数(数值表达式)的值
(1)moval,23hAND45hOR67h
(2)movax,1234h/16+10h
3:
movax,23hSHL4
4:
moval,‘a’and(NOT(‘a’-‘A’))
5:
movax,(76543LT32768)XOR7654h
(1)al=67h
(2)ax=133h,dx=4h
(3)ax=0230h
(4)al=41h
(4)ax=7654h
3.10画图说明下列语句分配的存储空间及初始化的数据值
(1)byte_vardb‘abc’,10,10h,‘EF’,3dup(-1,?
3,dup(4))
(2:
)word_vardw10h,-5,3,dup(?
)
(1)
41h
42h
43h
10
10h
45h
46h
-1
?
4
?
(2)
00h
0fbh
0ffh
3.11
请设置一个数据段,按照如下要求定义变量:
(1)my1b为字符串常量,表示字符串“personalComputer”
(2)my2b为用十进制数表示的字节变量,这个数的大小为20
(3)my3b为用十六进制数表示的字节变量,这个数的大小为20
(4)my4b为用二进制数表示的字节变量,这个数的大小为20
(5)my5w为20个未赋值的字变量
(6)my6c为100的符号常量
(7)my7c为字符串常量,代替字符串“personalComputer”
.data
my1bdb'
PersonalComputer'
my2bdb20
my3bdb14h
my4bdb00010100b
my5wdw20dup(?
my6c=100
my7c=<
>
3.12希望控制变量或程序代码在段中的偏移地址,应该使用哪个伪指令?
利用定位伪指令控制,如org,even,align
3.13名字和符号有什么属性?
包括逻辑地址和类型两种属性。
3.14设在某个程序中有如下片段,请写出每条传送指令执行后寄存器AX的内容:
;
数据段
Org100h
Varwdw1234h,5678h
Varbdb3,4
Varddd12345678h
Buffdb10dup(?
Messdb‘hello’
;
代码段
Movax,offsetmess
Movax,typebuff+typemess+typevard
Movax,sizeofvarw+sizeofbuff+sizeofmess
Movax,lengthofvarw+lengthofvard
org100h
varwdw1234h,5678h
varbdb3,4
varddd12345678h
buffdd10dup(?
messdb'
Hello'
movax,offsetvarb+offsetmess
movax,typebuff+typemess+typevard
movax,sizeofvarw+sizeofbuff+sizeofmess
movax,lengthofvarw+lengthofvard
3.15假设myword是一个字变量,mybyte1和mybyte2是两个字节变量,指出下列语句中的具体错误原因。
(1)movbyteptr{bx},1000
(2)movbx,offsetmyword{si}
(3)cmpmybyte1,mybyte2
(4)movmybyte1,al+1
(5)subal,myword
(6)jnzmyword
(1)1000超过一个字节所能表达的最大整数
(2)SI应为偶数
(3)两个内存单元不能直接运算
(4)应改为[al+1]
(5)条件转移指令后面应接标号,而不是变量
3.16编写一个程序,把从键盘输入的一个小写字母用大写字母显示出来
movah,1;
只允许输入小写字母
int21h
subal,20h;
转换为大写字母
movdl,al
movah,2
int21h;
显示
3.17已知用于LED数码管的显示代码表为:
LEDtabledb0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h
db80h,90h,88h,83h,0c6h,0c1h,86h,8eh
它依次表示0~9,A~F这16个数码的显示代码。
现编写一个程序实现将lednum中的一个数字(0~9,a~f)转换成对应的LED显示代码
movbx,offsetLEDtable
moval,lednum
xlat
3.18编制一个程序,把变量bufX和bufY中较大者存入bufZ;
若两者相等,则把其中之一存入bufZ中。
假设变量存放的是8位有符号数。
movax,bufX
cmpax,bufY
jaedone
movax,bufY
done:
movbufZ,ax
3.19为有符号16位数,请将它们的符号状态保存在signX,即:
如果变量值大于等于0,保存0;
如果X小于0,保存-1。
编写该程序。
设变量bufX解:
.modelsmall
.stack
.data
bufXdw-7
signXdb?
.code
.startup
cmpbufX,0;
testbufX,80h
jlnext;
jnznext
movsignX,0
jmpdone
next:
movsignX,-1
.exit0
end
3.20bufX、bufY和bufZ是3个有符号16进制数,编写一个比较相等关系的程序
(1)如果这3个数都不相等,则显示0
(2)如果这三个数中有两个数相等,则显示1
(3)如果这三个数都相等,则显示2
movdl,’2’
movax,bufX
cmpax,bufY
jenext1
decdl
next1:
cmpax,bufZ
jenext2
next2:
3.21例3.7中,如果要实现所有为1的位都顺序执行相应的处理程序段(而不是例题中仅执行最低为1位的处理程序段),请写出修改后的代码段?
;
moval,number
movbx,0;
BX←记录为1的位数
restart:
cmpal,0;
AL=0结束
jzdone
again:
shral,1;
最低位右移进入CF
jcnext;
为1,转移
incbx;
不为1,继续
jmpagain
pushax
pushbx
shlbx,1;
位数乘以2(偏移地址要用2个字节单元)
jmpaddrs[bx];
间接转移:
IP←[table+BX]
以下是各个处理程序段
fun0:
movdl,'
0'
jmpdisp
fun1:
1'
fun2:
2'
fun3:
3'
fun4:
4'
fun5:
5'
fun6:
6'
fun7:
7'
disp:
movah,2;
显示一个字符
popbx
popax
jmprestart
…
3.22编制程序完成12H、45H、0F3H、6AH、20H、0FEH、90H、0C8H、57H和34H等10个字节数据之和,并将结果存入字节变量SUM中(不考虑溢出和进位)。
wjxt322.asm
b_datadb12h,45h,0f3h,6ah,20h,0feh,90h,0c8h,57h,34h;
原始数据
numequ10;
数据个数
sumdb?
预留结果单元
xorsi,si;
位移量清零
xoral,al;
取第一个数
movcx,num;
累加次数
addal,b_data[si];
累加
incsi;
指向下一个数
loopagain;
如未完,继续累加
movsum,al;
完了,存结果
3.23求主存0040h:
0开始的一个64KB物理段中共有多少个空格?
;
wjxt323.asm
start:
movax,0040h;
送段地址
movds,ax
movsi,0;
偏移地址
movcx,si;
计数(循环次数)
xorax,ax;
空格计数器清零
cmpbyteptr[si],20h;
与空格的ASCII码比较
jnenext;
不是空格,转
incax;
是空格,空格数加1
修改地址指针
cx=cx-1,如cx=0退出循环
endstart
3.24编写计算100个16位正整数之和的程序。
如果和不超过16位字的范围(65535),则保存其和到wordsum,如超过则显示‘overflow’。
答:
countequ100
parraydwcountdup(?
);
假设有100个数据
wordsumdw0
msgdb‘overflow’,’$’
movcx,count
movax,0
movbx,offsetparray
addax,[bx]
jncnext
movdx,offsetmsg
movah,9
显示溢出信息
jmpdone;
然后,跳出循环体
addbx,2
loopagain
movwordsum,ax
…
3.25编程把—个16位无符号二进制数转换成为用8421BCD码表示的5位十进制数。
转换算法可以是:
用二进制数除以10000,商为“万位”,再用余数除以1000,得到“千位”;
依次用余数除以l00、10和l,得到“百位”、“十位”和“个位”。
wjxt325.asm
.modelsmall
.stack256
.data
arraydw?
源字数据
dbcddb5dup(?
五位bcd结果,高对高低对低
.code
.startup
movdx,array;
取源数据(余数)
movbx,10000;
除数
movcx,10;
除数系数
movsi,4;
目的数据高位位移量
movax,dx;
dx.ax中存放被除数
movdx,0
divbx;
除于bx,商ax,余数dx
movdbcd[si],al;
商<10,存结果
pushdx;
暂存余数
movax,bx;
除数除于10
movdx,0
divcx;
dx.ax除于cx,商ax、余数0存在dx
movbx,ax;
bx是除数
popdx
decsi;
目的数据位移量减1
jnzagain
movdbcd,dl;
存个位数(<
10)
3.26过程定义的一般格式是怎样的?
子程序开始为什么常有PUSH指令?
返回钱为什么常有POP指令?
下面完成16位无符号数累加的子程序有什么不妥吗?
若有,请改正。
CarzyPROC
Pushax
Xorax,ax
Xorax,dx
Againaddax,[bx]
Adcdx,0
Incbx
Loopagain
Ret
ENDPcrazy
(1)汇编语言中,子程序要用一对过程伪指令PROC和ENDP声明,格式如下:
过程名PROC[NEAR|FAR]
……;
过程体
过程名ENDP
(2)保护用到的寄存器内容,以便子程序返回时进行相应的恢复。
(3)改错:
crazyproc
pishbx
pushcx
xorax,ax
xordx,dx
again:
adda,[bx]
adcdx,0
incbx
loopagain
popcx
popbx
3.27编写一个源程序,在键盘上按一个键,将从AL返回的ASCⅡ码值显示出来,如果按下ESC键则程序退出。
解(不需调用HTOASC子程序):
movah,1
cmpal,1bh;
ESC的ASCII码是1bh
jedone
是大写字母则转换为小写字母
3.28请按如下说明编写子程序:
子程序功能:
把用ASCⅡ码表示的两位十进制数转换为对应二进制数
入口参数:
DH=十位数的ASCⅡ码,DL=个位数的ASCⅡ码
出口参数:
AL=对应的二进制数
解答:
asctobproc
pushcx
anddh,0fh;
先转换十位数
shldh,1;
十位数乘以10(采用移位指令)
movch,dh
shldh,1
adddh,ch
anddl,0fh;
转换个位数
adddh,dl;
十位数加个位数
moval,dh;
设置出口参数
popcx
ret
asctobendp
3.29调用HTOASC子程序,显示一个字节的16进制数,后跟“H”的子程序。
DIPASCproc;
入口参数:
AL=要显示的一个16进制数
pushdx
movcl,4;
转换高位
shral,cl
callHTOASC
movdl,al;
popax;
转换低位
movdl,’H’;
显示一个字母“H”
DIPASCendp
HTOASCproc;
将AL低4位表达的一位16进制数转换为ASCII码
andal,0fh
cmpal,9
jbehtoasc1
addal,37h;
是0AH~0FH,加37H转换为ASCII码
ret;
子程序返回
htoasc1:
addal,30h;
是0~9,加30H转换为ASCII码
HTOASCendp
3.30写一个子程序,根据入口参数AL=0、1、2,依次实现对大写字母转换成小写、小写转换成大写或大小字母互换。
欲转换的字符串在string中,用0表示结束
lucaseproc
movbx,offsetstring
cmpal,0
jecase0
cmpal,1
jzcase1
cmpal,2
jzcase2
case0:
cmpbyteptr[bx],0
cmpbyteptr[bx],’A’
jbnext0
cmpbyteptr[bx],’Z’
janext0
addbyteptr[bx],20h
next0:
incbx
jmpcase0
case1:
cmpbyteptr[bx],’a’
jbnext1
cmpbyteptr[bx],’z’
janext1
subbyteptr[bx],20h
jmpcase1
case2:
jbnext2
janext20
jmpnext2
next20:
janext2
jmpcase2
lucaseendp
3.31子程序的参数传递有哪些方法?
请简单比较
(1)用寄存器传递参数:
最简单和常用的参数传递方法是通过寄存器,只要把参数存于约定的寄存器中就可以了
由于通用寄存器个数有限,这种方法对少量数据可以直接传递数值,而对大量数据只能传递地址
采用寄存器传递参数,注意带有出口参数的寄存器不能保护和恢复,带有入口参数的寄存器可以保护、也可以不保护,但最好能够保持一致
(2)用共享变量传递参数
子程序和主程序使用同一个变量名存取数据就是利用共享变量(全局变量)进行参数传递
如果变量定义和使用不在同一个源程序中,需要利用PUBLIC、EXTREN声明
如果主程序还要利用原来的变量值,则需要保护和恢复
利用共享变量传递参数,子程序的通用性较差,但特别适合在多个程序段间、尤其在不同的程序模块间传递数据
(3)用堆栈传递参数
参数传递还可以通过堆栈这个临时存储区。
主程序将入口参数压入堆栈,子程序从堆栈中取出参数;
子程序将出口参数压入堆栈,主程序弹出堆栈取得它们
采用堆栈传递参数是程式化的,它是编译程序处理参数传递、以及汇编语言与高级语言混合编程时的常规方法
3.32采用堆栈传递参数的一般方法是什么?
为什么应该特别注意堆栈平衡问题。
方法:
主程序将入口参数压入堆栈,