1、总汇编语言编程编程练习汇编语言编程编程练习一、实验题1.非数值运算编程 (a)实验目的 通过非数值运算(如统计,分类,排序,代码转换等)编程,进一步掌握 8086/8088 汇 编语言程序设计方法和技巧 (b)实验容 统计 设有100H个数,编程统计正数、负数和零的个数。 实验分析: 程序中数的总数很多,某些部分需要重复执行,因此要用到循环结构。循环结构 每次测试循环条件,当满足条件时,重复执行这一段程序;否则循环结束,顺序往下 执行。 其次,要统计正数、负数、零的个数,可以依靠标志位SF进行判断,SF=0,正 数;SF=1,负数;零则为总数减去正负数的个数。 该程序流程图如下: NOYES程
2、序如下所示: STACK SEGMENT STACKDW 128 DUP(?)STACK ENDS DATA SEGMENTBUFF DB 256 DUP(?)MEM1 DB ?MEM2 DB ?MEM3 DB ?DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX MOV CX,256 LEA BX, BUFF XOR DL,DL XOR DH,DH XOR SI,SI ;统计计数器清0 NEXT:MOV AL,BX;取数据到AL ADD AL,0 ;做运算,影响标志位SF JNS AA1 ;是正数,跳
3、到AA1 INC DL ;是负数,统计加1 AA1: INC DH ;是正数,加1 INC BX ;移动指针 LOOP NEXT ;循环控制 MOV MEM1,DL MOV MEM2,DH MOV MEM3,SI ;保存统计结果 MOV AX,4C00H INT 21HCODE ENDS END START 代码转换 编程将组合的BCD码9649转换成二进制数,考虑采用(A*10)+B)*10)+C)*10+D 的算法。 实验分析: 由学习已知,写成十六进制的BCD码和十进制码是完全一样的,比如,75D= (01110101)BCD,而(01110101)B=75H。BCD码的运算也遵循十进制
4、运算 规则,这一点可以方便计算机本身擅长的二进制运算结合BCD码的调整指 令来完成。 本题中,由于9469H计算机会默认为二进制数。因而,我们首先要做的是将 9469h BCD 码先转换成十进制数,计算机将会以二进制形式存储。最后再辅 助程序令其输出在屏幕上。 实验大抵流程如下: 实验代码如下:DATAS SEGMENT buffer1 DW 9649h buffer2 DW ? ;分配两个字节的空间 DATAS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS START: MOV AX,DATAS MOV DS,AX mov ax,buffer1 an
5、d ax,0f000h mov cl,12 shr ax,cl mov dx,ax ;至此,已将9649h(BCD)中的9(十进制)取出,并放入dx中 call change ;调用chang,将9乘以10 mov ax,dx mov bx,buffer1 and bx,0f00h mov cl,8 shr bx,cl add ax,bx mov dx,ax call change mov ax,dx mov bx,buffer1 and bx,00f0h mov cl,4 shr bx,cl add ax,bx mov dx,ax call change mov ax,dx mov bx,b
6、uffer1 and bx,000fh add ax,bx ;至此,ax中的值已是9649(十进制),但电脑是将其以二进制的形式存 储的,故应是25B1h,二进制就是10001 mov buffer2,ax ;因为后面会用到ah,为避免在其过程中丢失ax中的数据,故将ax 中的数据放入buffer2中 mov cx,16 again:shl buffer2,1 ;将已经转换成二进制的数逐个显示出来 mov dl,0 adc dl,30h mov ah,2 int 21h loop again mov ah,4CH INT 21H change proc ;子程序change的功能是实现dx乘以
7、10 add dx,dx mov cx,dx add dx,dx add dx,dx add dx,cx ret change ENDPCODES ENDS END START 排序 将80H个无符号的八位二进制数按递增方式排列。同时考虑它们有符号数、递减等 方式。 实验分析: 实验要求将数排序,则用CMP比较两个数大小,用标志位JNG(有符号位不 大于),JGE(有符号位不小于),JAE(无符号位不低于)来判定排序种类。 准备将该题用“冒泡排序法”,将其两两比较。前一个数较大(递减),则不会 改变原来位置;否则,两数交换,依次将全部数据排序依次(小循环)。示例 如下: 13 -39 96 8
8、4 -75 58 13 96 84 -39 58 -75 96 84 13 58 -39 -75 96 84 58 13 -39 -75 不过,由于数据的原始情况不知,按以上方法排序一次不一定符合要求。本题 采取多次小循环方法,用数据个数控制循环次数。这种方法效率低,不过在循环次 数较少的情况下还是很简单的,毕竟原理很简单。 该程序流程图如下: NO YESNO YES 进入小循环直到数按照从大到小的顺序排列好为止。 附程序如下:1)、无符号位从小到大: STACK SEGMENT STACKDW 64 DUP(?)STACK ENDS DATA SEGMENTBUFF DB 128 DUP(
9、?)COUNT EQU $-BUFF ;等值命令DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX MOV CX,COUNT-1LOOP1:MOV DX,CX ;保存循环次数 MOV SI,0 ;采用变址寻址LOOP2:MOV AL,BUFFSI CMP AL,BUFFSI+1;前数与后数比 JNA COT ;前个数小于(或等于),转(无符号) XCHG AL,BUFFSI+1;否则交换存位置 MOV BUFFSI,AL COT: INC SI LOOP LOOP2 ;所有数据排列一次 MOV CX,D
10、X ;开始下一次排序 LOOP LOOP1 MOV AX,4C00H INT 21HCODE ENDS END START2)、无符号位从大到小STACK SEGMENT STACKDW 64 DUP(?)STACK ENDS DATA SEGMENTBUFF DB 128 DUP(?)COUNT EQU $-BUFF ;等值命令DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX MOV CX,COUNT-1LOOP1:MOV DX,CX MOV SI,0LOOP2:MOV AL,BUFFSI CMP
11、AL,BUFFSI+1 JNG COT ;前个数小于(或等于),转(有符号) XCHG AL,BUFFSI+1 MOV BUFFSI,ALCOT: INC SI LOOP LOOP2 MOV CX,DX LOOP LOOP1 MOV AX,4C00H INT 21HCODE ENDS END START3)、有符号位递减STACK SEGMENT STACKDW 64 DUP(?)STACK ENDS DATA SEGMENTBUFF DB 128 DUP(?)COUNT EQU $-BUFF ;等值命令DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATAS
12、TART:MOV AX,DATA MOV DS,AX MOV CX,COUNT-1LOOP1:MOV DX,CX MOV SI,0LOOP2:MOV AL,BUFFSI CMP AL,BUFFSI+1 JGE COT ;前个数大于(或等于),转(有符号) XCHG AL,BUFFSI+1 MOV BUFFSI,ALCOT: INC SI LOOP LOOP2 MOV CX,DX LOOP LOOP1 MOV AX,4C00H INT 21HCODE ENDS END START2、数值运算编程(a)实验目的 通过编程及程序调式,熟悉 8086/8088 运算指令及 DEBUG 动态调试程序的方
13、法(b)实验容 无符号二进制数运算 已知有 20 个 8 位的无符号二进制数,编一个程序完成对这些数的求和。 实验分析: 求20个无符号的八位二进制数,直接进行二进制运算要将数值转换成二进制 形式比较繁琐。由此想到写成十六进制的BCD码和十进制码是完全一样的, 比如,75D= (01110101)BCD,而(01110101)B=75H。BCD码的运算也遵 循十进制运算规则,这一点可以方便计算机本身擅长的二进制运算结合BCD 码的调整指令来完成。 将输入的20个无符号八位二进制数看成BCD码的十六进制表示,直接进行 BCD加法运算。最终将结果转换成以ASCII码形式输出,即为所得数的十六 进制
14、BCD码形式。 流程图略。 实验代码如下(参考):STACK SEGMENT STACK STACK ; STACK SEGMENTDW 128 DUP(?) ; 128 WORDSSTACK ENDS ; SEGMENT ENDDATA SEGMENT PARA DATA ; DATA SEGMENTTABLE DB 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20TOTAL DW ? ;BCD 加法运算结果PRINT DB ? ;显示的 ASCII 字符DATA ENDS ; SEGMENT ENDCODE SEGMEN
15、T PARA CODEASSUME CS:CODE, DS:DATA, SS:STACKMAIN PROC FAR PUSH DS SUB AX,AX PUSH AX ;DS:0000为返回地址 MOV AX,DATA MOV DS,AX ;DS初始化 MOV AX,0 LEA BX,TABLE ;DS:BX指向TABLE的首地址 MOV CX,20 ;循环20次SUM: ADD AL,BX JNC OVER INC AH CLCOVER: INC BX LOOP SUM MOV TOTAL,AX MOV CX,0010 LEA SI,PRINT+3L20: CMP AX,CX ;值10? J
16、B L30 ;是,退出 XOR DX,DX ;清除高位商 DIV CX ;除以 10 OR DL,30H MOV SI,DL ;存 ASCII 字符 DEC SI JMP L20L30: OR AL,30H ;存最后的商 MOV SI,AL ;作为 ASCII 字符 MOV AH,02H ;打印算术结果 ; MOV CX,4 LEA DI,PRINTL10: MOV DL,DI INT 21H INC DI LOOP L10 MOV AX,4C00H INT 21HMAIN ENDPCODE ENDSEND MAIN BCD算术运算 已知两个 6 位的 BCD 码,完成减法运算,设被减数为 1
17、23456,减数为 789123 实验分析: 本题中先做减法,再采用未组合的BCD码减法调整,从低位开始逐位做减法运算。 将计算结果低位存入AL,高位存于AH。总体来说,该题原理较为简单。实验代码如下(参考): STACK SEGMENT STACKDW 128 DUP(?)STACK ENDSDATA SEGMENT PARADATANUMBER1 DB 789123NUMBER2 DB 123456SF DB - ;需打印的符号RESULT DB ? ;存算术结果DATA ENDSCODE SEGMENT PARACODEASSUME CS:CODE,DS:DATA,SS:STACKMAI
18、N PROC FAR PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX LEA SI,NUMBER1+5 LEA DI,NUMBER2+5 LEA BX,RESULT+5 MOV CX,6 CLC MOV AL,SI ;将低位放在 AL 中L10: MOV AH,SI-1 ;将高位放在 AH 中 SBB AL,DI AAS ;做 ASCII 减法调整 OR AX,3030H MOV BX,AL ;存单位运算结果 MOV AL,AH ;将下一位放入 AL DEC SI DEC DI DEC BX LOOP L10 MOV AH,02H ;打印算术结果
19、 MOV CX,7 LEA DI,SFL20: MOV DL,DI INT 21H INC DI LOOP L20 MOV AX,4C00H INT 21HMAIN ENDPCODE ENDS END MAIN2、实验总结 通过数值与非数值题型的练习,有效复习巩固了对汇编整体编程结构的理解和练习。对其一些较常用的指令也有了一定的认识,对汇编中的循环、跳转结构尤其运用多,这就需要我们更加多多练习,以便熟悉掌握汇编编程。汇编很是繁琐,有时C语言中的一句话,它可能要用好几句才能描绘相同的意思。自己在编程时也问了很多同学,借鉴了很多参考资料,甚至还copy了不少人的心血。不过觉得自己整体编程感觉还未完全形成,还需多加练习。不过,真的感觉汇编难,有时就是不知道该如何下手。还有其中各种堆栈,各种寄存器感觉也比较晕,指令更是多得不过,还是想多懂点程序。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1