1、 汇编语言编程 实验报告 学号: 姓名: 成绩: - 2 -目录 一、实验一: . 错误!未定义书签。 二、实验二: . 4 三、实验三: . 8 四、实验四: 10 五、实验五: . 错误!未定义书签。 六、实验六: 19 七、汇编实验总结 23 - 3 -实验一 一 实验题目 【汇编语言补充作业T20】编写完整程序,利用DOS系统功能调用,从键盘输入一个字符串,并将该字符串从屏幕上换行后并输出。 二 程序流程及思路 实现字符串输入,需要分成三个步骤: 1、在数据段中定义一个缓存区为存放字符串做准备; 2、DOS系统功能调用0AH号子功能,(DS:DX)= 输入缓冲区首址; 3、在输入的字符
2、串尾加上$字符,以作为输出结束条件。 实现字符串输出,则需要注意的问题是: 1、缓冲区第三个字节才开始存放输入的字符,前两个字节分别存放缓冲区长度和字符串实际字符数; 2、输出回车换行可利用字符串:CR DB 0AH,0DH,$。 三 源程序清单 DATA SEGMENT N EQU 50 MAXLEN DB N ;缓冲区字符的最大长度 ACTLEN DB ? ;实际字符个数 STRING DB N DUP(?) ;字符空间 CR DB 0AH,0DH,$ DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK START: MOV AX,
3、DATA MOV DS,AX LEA DX,MAXLEN MOV AH,0AH INT 21H ;字符串输入 MOV AH,09H LEA DX,CR INT 21H ;回车换行 MOV BL,MAXLEN+1 ;取实际的字符长度 MOV BH,0 LEA SI,MAXLEN+2 ;取字符开始的首地址 - 4 -MOV BYTE PTR SI+BX,$ ;输出结尾要加上$ MOV DX,SI ;把开始存放字符的首地址赋给DX MOV AH,09H INT 21H MOV AH,4CH INT 21H CODE ENDS END START 四 结果拷屏 - 5 -实验二 一. 实验题目 【汇编
4、语言补充作业T23】假设CX:BX中存放了4为非压缩的BCD码表示的十进制数4386,请编写完整程序将这个数转化成2进制数并存放到DI寄存器中。 二. 程序流程及思路 首先,要解决以上问题需分三个步骤进行: 1、将CX:BX中的非压缩BCD码调整成压缩BCD码。这有两种方法: a、利用非压缩BCD码调整指令AAD,达到以上目的; b、利用移位指令,将两个非压缩BCD码进行整合,达到以上目的; (注:以下程序采用b方法) 2、将调整后的压缩BCD码转化为十进制数。调整后b3b2=43,b1b0=86。转化方法为b3b2*100+b1b0 DI。计算结果送入DI寄存器中。 由于100=64+32+
5、4,因此考虑用移位指令进行BCD码的乘法运算。 3、利用移位指令编写一段代码进行结果输出,以便于在屏幕上直接进行核对检验。 三源程序清单 DATA SEGMENT DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK start: mov ch,04 mov cl,03 mov bh,08 mov bl,06 ; mov al,ch mov ah,0 shl ax,1 ;ch位乘10(10=8+2) mov si,ax shl ax,1 shl ax,1 add ax,si ; mov ch,0 add ax,cx - 6 -mov dx
6、,ax ;dx=43 shl dx,1 shl dx,1 mov ax,dx shl dx,1 shl dx,1 shl dx,1 add ax,dx shl dx,1 ; add dx,ax ;dx乘以100(100=64+32+4) mov al,bh mov ah,0 mov si,0 shl ax,1 ;bh位乘10 mov si,ax shl ax,1 shl ax,1 add ax,si ; mov bh,0 add ax,bx add dx,ax mov di,dx show: mov cl,4 ;该段进行结果输出检验 mov bx,dx shr bh,cl mov dl,bh
7、add dl,30h mov ah,2 int 21h ;1位 mov bh,dh and bh,0Fh mov dl,bh add dl,30h mov ah,2 int 21h ;2位 mov dh,bl shr dh,cl mov dl,dh add dl,30h - 7 -mov ah,2 int 21h ;3位 mov dh,bl and dh,0Fh mov dl,dh add dl,30h mov ah,2 int 21h ;4位 mov ah,4ch int 21h code ends end start 五 结果拷屏 输出结果为1122十六进制,将题目中4386换成4096,
8、输出如下,为1000十六进制: - 8 - 9 -实验三 一实验题目 【汇编语言补充作业T22】已知有以下数据段定义: NUM DW 3570 STRING DB 5 DUP(20H),$;20H为空格的ASCII码 请编写完整程序,在屏幕上以十进制的形式将 NUM这个数打印出来,可以借助STRING这个字符串。(NUM这个数可以定义为一个任意字型数) 二程序流程及思路 考虑到NUM在寄存器中以十六进制数的形式进行存放,转化成十进制数可能最大值为65535,则输出刚好输出的十进制数位数为5位。 因此,需要除以10000d,1000d,100d,10d,1d来分别取出该数各位数值,并在屏幕上连续
9、打印。其过程为: 1、将NUM先存入寄存器SI中,除数为10000d; 2、除法完成后,商直接输出,余数保留并且存入SI中; 3、依次将除数换成1000d,100d,10d,1d,重复2操作,直到程序结束。 另外,程序打印每一位所执行的动作需要重复五次,因此将该过程写成一个子程序(chufa)进行调用,可以简化代码,使得程序可读性更强,程序健壮性更好。 三源程序清单 DATA SEGMENT NUM DW 3570 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK start: MOV AX,DATA MOV DS,AX mov si
10、,num mov cx,10000d call chufa mov cx,1000d call chufa mov cx,100d call chufa mov cx,10d call chufa mov cx,1d - 10 - call chufa mov ah,4Ch int 21h chufa: mov ax,si ;si 存储的是要输出的十进制数据 mov dx,0 div cx mov si,dx ;余数赋给si 寄存器,为下一步出发做准备 mov dl,al add dl,30h mov ah,2 int 21h ;除法的商直接输出 ret code ends end start
11、 四结果拷屏 以上为NUM=3570d时程序输出结果为03570,若将NUM改为1122H,则输出如下,结果为04386: - 11 - 12 - 实验四 一实验题目 【汇编语言补充作业T13】请编写完整程序在一个升序字节数组中查找数N,找到后将此数从数组中删除,并使得CF=0;没找到返回CF=1。数组的首地址和末地址为A_HEAD和A_END。 二程序流程及思路 删除升序数组中的一个数N的关键步骤是将这个数搜索出来。若搜索到,则进行删除,然后对整个数组进行调整;若未搜索到,则无操作动作。其中进行搜索的方法为逐个比较。 程序流程图如下: 开始 初始化数组ARRAY_HEAD,ARRAY_END
12、,目标数N BXARRAY_HEAD, BX=ARRAY_END BX=N DELETE:CF0,ARRAY_ENDARRAY_END-1,调整 EXIT:CF1 BXBX+1 结束 Y Y N N - 13 - 三源程序清单 DATA SEGMENT ARRAY DB 1,2,3,4,5,6,7,8,9,0 LENG EQU $-ARRAY ARRAY_END DW ? ARRAY_HEAD DW ? NUM DB 5 DATA ENDS STACK SEGMENT STACK STACK ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACK S
13、TART: MOV AX,DATA MOV DS,AX MOV AL,LENG CBW MOV BX,OFFSET ARRAY MOV ARRAY_HEAD,BX ADD AX,BX MOV DI,AX DEC DI MOV ARRAY_END,DI MOV AX,0 MOV AL,NUM L1: MOV DL,0 MOV DL,BX CMP DL,AL ;当前数与NUM进行比较 JNE L2 ;不相等跳转至L2 JMP DELETE ;相等跳转至DELETE L2: INC BX CMP BX,ARRAY_END JBE L1 ;指针+1,并循环 STC JMP EXIT DELETE:MO
14、V DI,ARRAY_END SUB DI,BX - 14 - MOV CX,DI DEL: MOV DX,BX+1 ;将BX之后的数依次前移一位 MOV BX,DX INC BX LOOP DEL DEC ARRAY_END ;删除后ARRAY_END前移 CLC JMP EXIT EXIT: MOV CX,0 MOV CX,ARRAY_END MOV AX,OFFSET ARRAY SUB CX,AX INC CX MOV BX,0 SHOW: MOV DL,ARRAY+BX ;将删除后数组元素打印以检验 ADD DL,30H MOV AH,2 INT 21H INC BX LOOP SH
15、OW MOV AH,4CH INT 21H CODE ENDS END START 四结果拷屏 - 15 - 以上输出为在1、2、3、4、5、6、7、8、9、0数组中删去N=5的结果 调用debug-t命令可以查看CF标志位状态: 可见,CF位为0,若当N=10,在数组里未找到目标数,则结果为: 可见数组元素不变,且CF=1 - 16 - 实验五 一实验题目 【汇编语言补充作业T14】请编写完整程序从键盘读取字符,如果是十进制的09,则在屏幕上输出该数的八位二进制码,并将数字依次存放到BUF开头的数组中;如果读取的字符是Q或者q,则程序退出;其他情况在屏幕上打印“You must input
16、0-9 or q or Q”。 (如输入的字符是9,则输出00001001) 提示:输出一个数的2进制形式应该从最高位开始输出,可以将此段程序定义为一个过程。 二程序流程及思路 总体流程: 1、利用DOS系统功能调用21H 的01号子功能读取键盘输入的一个字符x,换行,然后将x与0、9的ASCII码进行比较,若在09范围内,则跳至2;不在该范围内跳至3; 2、打印该数的二进制形式,将该数存入数组BUF中,换行,跳至1; 3、将x与Q、q的ASCII码进行比较,若相等,则打印数组内容,退出程序;否则,跳至4; 4、打印字符串“You must input 0-9 or q or Q”,换行,跳至
17、1; 由以上过程看出,程序的唯一退出条件为输入字符q或Q。 流程图如下图: 二进制形式打印定义的过程如下: 初始化:除数A=128(2的7次方),被除数为B 1、B除以A,打印商,B余数,AA/2。若A=1,跳至2;否则,重复1; 2、退出打印。 另外,程序定义变量 B_END作为数组的尾指针,当符合输出规则,将输入的数存放入数组BUF中,尾指针后移一位。这样定义便于在输出数组的时候定制结束条件。 程序中定义数组的大小20个字节。 - 17 - 三源程序清单 DATA SEGMENT MESSAGE DB You must input 0-9,or“q“or“Q“,$ CR DB 0AH,$
18、BUF DB 20 DUP(0) B_END DW ? NUM DB 2 DATA ENDS STACK SEGMENT STACK STACK ENDS 开始 初始化数组尾指针B_END X=0 X=q或X=Q ERROR:打印错误提示 以二进制形式打印X B_END X B_ENDB_END+1 打印数组元素 结束 N Y N Y 读取键盘输入的字符X - 18 - CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACK START: MOV AX,DATA MOV DS,AX MOV AX,OFFSET BUF ;空数组时尾指针指向数组起始地址 MOV
19、B_END,AX DEC B_END MOV AX,0 L: MOV AH,1 ;输入字符 INT 21H CMP AL,30H JB ERROR ;小于30H,跳转至ERROR CMP AL,39H JBE NEXT ;=30H且=1 N进栈 NN-1 ERROR 结束 Y N FAC递归调用 弹出N FACN*FAC 递归返回 N=q Y N - 23 - CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACK START: MOV AX,DATA MOV DS,AX L: MOV AH,1 INT 21H CMP AL,31H ;判断输入的字符是否合法
20、JB ERROR CMP AL,36H JA ERROR SUB AL,30H CALL FAC MOV RESULT,DX MOV SI,DX CALL CRLF ;换行 MOV CX,1000d ;以十进制数的形式打印 CALL SHOW MOV CX,100d CALL SHOW MOV CX,10d CALL SHOW MOV CX,1d CALL SHOW CALL CRLF ;换行 MOV DX,RESULT ;还原DX的值 JMP L SHOW PROC MOV AX,SI ;si 存储的是要输出的十进制数据 MOV DX,0 DIV CX MOV SI,DX ;余数赋给si 寄
21、存器,为下一步出发做准备 MOV DL,AL ADD DL,30h MOV AH,2 INT 21h ;除法的商直接输出 RET SHOW ENDP CRLF PROC - 24 - PUSH AX ;数据保护 PUSH DX MOV AH,9 ;换行 LEA DX,CR INT 21H POP DX POP AX RET CRLF ENDP FAC PROC ;入口参数AL,出口参数N!=DX CMP AL,0 JNZ F1 MOV DX,1 RET F1: PUSH AX DEC AL CALL FAC ADD1: POP CX CALL MULT RET FAC ENDP MULT PROC MOV AL,CL MUL DL MOV DX,AX RET MULT ENDP ERROR: CMP AL,q ;输入q字符退出 JZ EXIT CALL CRLF ;换行 MOV AH,9 ;输出错误提示 LEA DX,MESSAGE INT 21H CALL CRLF ;换行 JMP L EXIT: MOV AH,4Ch ;退出程序 INT 21h CODE ENDS END START - 25 - 四结果拷屏