总汇编语言编程编程练习.docx
《总汇编语言编程编程练习.docx》由会员分享,可在线阅读,更多相关《总汇编语言编程编程练习.docx(16页珍藏版)》请在冰豆网上搜索。
![总汇编语言编程编程练习.docx](https://file1.bdocx.com/fileroot1/2022-12/1/253d98b8-3dbb-4e63-8ba6-65c7cccb0747/253d98b8-3dbb-4e63-8ba6-65c7cccb07471.gif)
总汇编语言编程编程练习
汇编语言编程编程练习
一、实验题
1.非数值运算编程
(a)实验目的
通过非数值运算(如统计,分类,排序,代码转换等)编程,进一步掌握8086/8088汇
编语言程序设计方法和技巧
(b)实验容
·统计
设有100H个数,编程统计正数、负数和零的个数。
实验分析:
程序中数的总数很多,某些部分需要重复执行,因此要用到循环结构。
循环结构每次测试循环条件,当满足条件时,重复执行这一段程序;否则循环结束,顺序往下执行。
其次,要统计正数、负数、零的个数,可以依靠标志位SF进行判断,SF=0,正数;SF=1,负数;零则为总数减去正负数的个数。
该程序流程图如下:
NO
YES
程序如下所示:
STACKSEGMENTSTACK
DW128DUP(?
)
STACKENDS
DATASEGMENT
BUFFDB256DUP(?
)
MEM1DB?
MEM2DB?
MEM3DB?
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVCX,256
LEABX,BUFF
XORDL,DL
XORDH,DH
XORSI,SI;统计计数器清0
NEXT:
MOVAL,[BX];取数据到AL
ADDAL,0;做运算,影响标志位SF
JNSAA1;是正数,跳到AA1
INCDL;是负数,统计加1
AA1:
INCDH;是正数,加1
INCBX;移动指针
LOOPNEXT;循环控制
MOVMEM1,DL
MOVMEM2,DH
MOVMEM3,SI;保存统计结果
MOVAX,4C00H
INT21H
CODEENDS
ENDSTART
·代码转换
编程将组合的BCD码9649转换成二进制数,考虑采用(((A*10)+B)*10)+C)*10+D的算法。
实验分析:
由学习已知,写成十六进制的BCD码和十进制码是完全一样的,比如,75D=(01110101)BCD,而(01110101)B=75H。
BCD码的运算也遵循十进制运算规则,这一点可以方便计算机本身擅长的二进制运算结合BCD码的调整指令来完成。
本题中,由于9469H计算机会默认为二进制数。
因而,我们首先要做的是将9469hBCD码先转换成十进制数,计算机将会以二进制形式存储。
最后再辅助程序令其输出在屏幕上。
实验大抵流程如下:
实验代码如下:
DATASSEGMENT
buffer1DW9649h
buffer2DW?
;分配两个字节的空间
DATASENDS
CODESSEGMENT
ASSUMECS:
CODES,DS:
DATAS
START:
MOVAX,DATAS
MOVDS,AX
movax,[buffer1]
andax,0f000h
movcl,12
shrax,cl
movdx,ax;至此,已将9649h(BCD)中的9(十进制)取出,并放入dx中
callchange;调用chang,将9乘以10
movax,dx
movbx,[buffer1]
andbx,0f00h
movcl,8
shrbx,cl
addax,bx
movdx,ax
callchange
movax,dx
movbx,[buffer1]
andbx,00f0h
movcl,4
shrbx,cl
addax,bx
movdx,ax
callchange
movax,dx
movbx,[buffer1]
andbx,000fh
addax,bx;至此,ax中的值已是9649(十进制),但电脑是将其以二进制的形式存储的,故应是25B1h,二进制就是10001
movbuffer2,ax;因为后面会用到ah,为避免在其过程中丢失ax中的数据,故将ax中的数据放入buffer2中
movcx,16
again:
shlbuffer2,1;将已经转换成二进制的数逐个显示出来
movdl,0
adcdl,30h
movah,2
int21h
loopagain
movah,4CH
INT21H
changeproc;子程序change的功能是实现dx乘以10
adddx,dx
movcx,dx
adddx,dx
adddx,dx
adddx,cx
ret
changeENDP
CODESENDS
ENDSTART
·排序
将80H个无符号的八位二进制数按递增方式排列。
同时考虑它们有符号数、递减等方式。
实验分析:
实验要求将数排序,则用CMP比较两个数大小,用标志位JNG(有符号位不大于),JGE(有符号位不小于),JAE(无符号位不低于)来判定排序种类。
准备将该题用“冒泡排序法”,将其两两比较。
前一个数较大(递减),则不会改变原来位置;否则,两数交换,依次将全部数据排序依次(小循环)。
示例如下:
13-399684-7558
139684-3958-75
96841358-39-75
96845813-39-75
不过,由于数据的原始情况不知,按以上方法排序一次不一定符合要求。
本题采取多次小循环方法,用数据个数控制循环次数。
这种方法效率低,不过在循环次数较少的情况下还是很简单的,毕竟原理很简单。
该程序流程图如下:
NO
YES
NO
YES
进入小循环直到数按照从大到小的顺序排列好为止。
附程序如下:
1)、无符号位从小到大:
STACKSEGMENTSTACK
DW64DUP(?
)
STACKENDS
DATASEGMENT
BUFFDB128DUP(?
)
COUNTEQU$-BUFF;等值命令
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVCX,COUNT-1
LOOP1:
MOVDX,CX;保存循环次数
MOVSI,0;采用变址寻址
LOOP2:
MOVAL,BUFF[SI]
CMPAL,BUFF[SI+1];前数与后数比
JNACOT;前个数小于(或等于),转(无符号)
XCHGAL,BUFF[SI+1];否则交换存位置
MOVBUFF[SI],AL
COT:
INCSI
LOOPLOOP2;所有数据排列一次
MOVCX,DX;开始下一次排序
LOOPLOOP1
MOVAX,4C00H
INT21H
CODEENDS
ENDSTART
2)、无符号位从大到小
STACKSEGMENTSTACK
DW64DUP(?
)
STACKENDS
DATASEGMENT
BUFFDB128DUP(?
)
COUNTEQU$-BUFF;等值命令
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVCX,COUNT-1
LOOP1:
MOVDX,CX
MOVSI,0
LOOP2:
MOVAL,BUFF[SI]
CMPAL,BUFF[SI+1]
JNGCOT;前个数小于(或等于),转(有符号)
XCHGAL,BUFF[SI+1]
MOVBUFF[SI],AL
COT:
INCSI
LOOPLOOP2
MOVCX,DX
LOOPLOOP1
MOVAX,4C00H
INT21H
CODEENDS
ENDSTART
3)、有符号位递减
STACKSEGMENTSTACK
DW64DUP(?
)
STACKENDS
DATASEGMENT
BUFFDB128DUP(?
)
COUNTEQU$-BUFF;等值命令
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVCX,COUNT-1
LOOP1:
MOVDX,CX
MOVSI,0
LOOP2:
MOVAL,BUFF[SI]
CMPAL,BUFF[SI+1]
JGECOT;前个数大于(或等于),转(有符号)
XCHGAL,BUFF[SI+1]
MOVBUFF[SI],AL
COT:
INCSI
LOOPLOOP2
MOVCX,DX
LOOPLOOP1
MOVAX,4C00H
INT21H
CODEENDS
ENDSTART
2、数值运算编程
(a)实验目的
通过编程及程序调式,熟悉8086/8088运算指令及DEBUG动态调试程序的方法
(b)实验容
·无符号二进制数运算
已知有20个8位的无符号二进制数,编一个程序完成对这些数的求和。
实验分析:
求20个无符号的八位二进制数,直接进行二进制运算要将数值转换成二进制形式比较繁琐。
由此想到写成十六进制的BCD码和十进制码是完全一样的,比如,75D=(01110101)BCD,而(01110101)B=75H。
BCD码的运算也遵循十进制运算规则,这一点可以方便计算机本身擅长的二进制运算结合BCD码的调整指令来完成。
将输入的20个无符号八位二进制数看成BCD码的十六进制表示,直接进行BCD加法运算。
最终将结果转换成以ASCII码形式输出,即为所得数的十六进制BCD码形式。
流程图略。
实验代码如下(参考):
STACKSEGMENTSTACK'STACK';STACKSEGMENT
DW128DUP(?
);128WORDS
STACKENDS;SEGMENTEND
DATASEGMENTPARA'DATA';DATASEGMENT
TABLEDB01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20
TOTALDW?
;BCD加法运算结果
PRINTDB?
;显示的ASCII字符
DATAENDS;SEGMENTEND
CODESEGMENTPARA'CODE'
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
MAINPROCFAR
PUSHDS
SUBAX,AX
PUSHAX;DS:
0000为返回地址
MOVAX,DATA
MOVDS,AX;DS初始化
MOVAX,0
LEABX,TABLE;DS:
BX指向TABLE的首地址
MOVCX,20;循环20次
SUM:
ADDAL,[BX]
JNCOVER
INCAH
CLC
OVER:
INCBX
LOOPSUM
MOVTOTAL,AX
MOVCX,0010
LEASI,PRINT+3
L20:
CMPAX,CX;值<10?
JBL30;是,退出
XORDX,DX;清除高位商
DIVCX;除以10
ORDL,30H
MOV[SI],DL;存ASCII字符
DECSI
JMPL20
L30:
ORAL,30H;存最后的商
MOV[SI],AL;作为ASCII字符
MOVAH,02H;打印算术结果
;MOVCX,4
LEADI,PRINT
L10:
MOVDL,[DI]
INT21H
INCDI
LOOPL10
MOVAX,4C00H
INT21H
MAINENDP
CODEENDS
ENDMAIN
·BCD算术运算
已知两个6位的BCD码,完成减法运算,设被减数为123456,减数为789123
实验分析:
本题中先做减法,再采用未组合的BCD码减法调整,从低位开始逐位做减法运算。
将计算结果低位存入AL,高位存于AH。
总体来说,该题原理较为简单。
实验代码如下(参考):
STACKSEGMENTSTACK
DW128DUP(?
)
STACKENDS
DATASEGMENTPARA'DATA'
NUMBER1DB'789123'
NUMBER2DB'123456'
SFDB'-';需打印的符号
RESULTDB?
;存算术结果
DATAENDS
CODESEGMENTPARA'CODE'
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
MAINPROCFAR
PUSHDS
SUBAX,AX
PUSHAX
MOVAX,DATA
MOVDS,AX
LEASI,NUMBER1+5
LEADI,NUMBER2+5
LEABX,RESULT+5
MOVCX,6
CLC
MOVAL,[SI];将低位放在AL中
L10:
MOVAH,[SI-1];将高位放在AH中
SBBAL,[DI]
AAS;做ASCII减法调整
ORAX,3030H
MOV[BX],AL;存单位运算结果
MOVAL,AH;将下一位放入AL
DECSI
DECDI
DECBX
LOOPL10
MOVAH,02H;打印算术结果
MOVCX,7
LEADI,SF
L20:
MOVDL,[DI]
INT21H
INCDI
LOOPL20
MOVAX,4C00H
INT21H
MAINENDP
CODEENDS
ENDMAIN
2、实验总结
通过数值与非数值题型的练习,有效复习巩固了对汇编整体编程结构的理解和练习。
对其一些较常用的指令也有了一定的认识,对汇编中的循环、跳转结构尤其运用多,这就需要我们更加多多练习,以便熟悉掌握汇编编程。
汇编很是繁琐,有时C语言中的一句话,它可能要用好几句才能描绘相同的意思。
自己在编程时也问了很多同学,借鉴了很多参考资料,甚至还copy了不少人的心血。
不过觉得自己整体编程感觉还未完全形成,还需多加练习。
不过,真的感觉汇编难,有时就是不知道该如何下手。
还有其中各种堆栈,各种寄存器感觉也比较晕,指令更是多得……不过,还是想多懂点程序。