汇编语言程序设计
实验报告
实验名称
循环结构与子程序设计实验
班
学
姓
日
成
级
号
名
期
绩
评 阅 人
软件学院
一、 实验目的与意义
汇编语言程序设计实验(上机练习)是必不可少的学习环节之一,也是检验掌握汇编语言
程序设计知识的手段之一。
通过上机练习,可以加深对课程知识的理解和掌握,通过本次实验,加深了对循环程序
设计的理解,掌握单重和多重循环的程序设计,掌握子程序和宏指令的程序的汇编,了解子
程序和宏指令给程序编写带来的方便。
二、 实验环境
操作系统:Windows xp
测试软件:editplus 3,masm 5.0
上机地点:综合楼 311
三、 实验的预习内容
⑴ 实验前必须掌握循环控制指令,串操作指令的汇编格式和操作功能,了解循环的控
制方法以及编制循环结构程序的技巧。
⑵ 对于实验 5,就是要掌握单重和多重循环指令的使用,灵活的运用寄存器,以及可
能会用到子程序的内容。
⑶ 对于实验 6,明确子程序的定义与调用、主程序子程序之间的转返过程,掌握宏汇
编提供的部分条件汇编与宏指令命令及其使用方法。
四、 实验的步骤与调试方法
⑴ 实验 1 的步骤:先将 5 个数分别定义到数据段中,然后将数据的首地址送到 si 中,
将数据个数送到 cx 中,然后一个一个的跟 64H(100)做比较,若有相等的,直接输出“Y”,
若比了 5 次都没找到相等,输出“N”,换一种做法就是使用 LODSB 指令,简化程序,LODSB
就相当于 AL<---DS:[SI],SI<---SI+1。
⑵ 实验 2 的步骤:先定义一个子程序,功能是输出两数相乘的结果,这样在之后的程
序中就可以调用这个子程序来输出结果,然后分别利用寄存器来输出被乘数、乘号、乘数、
等号和结果,其中内层循环是一个数的运算,而外层循环则是数的更换。
⑶ 实验 3 的步骤:想定义 2 个宏指令分别是求绝对值和求和,求绝对值是一个一个的
取数,遇到真的到下一个,遇到负的用 0 减去本身,求和是分别取 sum 数据段和当前数据
段的 1 字节的数进行相加,将加得的结果存到 sum 中去,这样就要调 2 次子程序。而使用
宏指令的时候,则简化了求和的方法,只要调用 1 次求和的宏指令就好了。
DW 13h,22h,-6h
DW 12h,41h,2h
Dw 3
DW 20 dup(?)
⑷ 异常与调试方法:
DATA1
DATA2
LEN
SUM
单个数据都定义成字类型的了,数的大小和性质都不对了,对于多个数组成一个数,要
每一个单个数必须是字节类型的,这样组成的一个数据才与用数据定义伪指令定义出来的具
有相同的性质与特性。改正如下:
;测试数据
;数据长度
;和
DATA1
DATA2
LEN
DB 13h,22h,-6h
DB 12h,41h,2h
DW 3
;测试数据
;数据长度
SUM
DB 20 dup(?)
;和
五、 实验数据与实验结果
Exp4 开始的五个数据 15h,0dh,64h,60h,62h,所以有 100,输出“Y”
然后将 64h 改为 52h,结果就是“N”了。
Exp5 输出九九乘法表
Exp6
当三个数分别是 13h,22h,6h 和 12h,41h,02h 时,初始如图所示
运行完后结果如下图,结果应该是 086325h
当输入的数是 13h,22h,-6h 和 12h,41h,-2h 时,初始如图所示
运行完后结果如下图,首先负的数都变成了正的,结果应该还是 086325h
当输入的数变成 13h,22h,-6h 和 12h,41h,2h 时,初始如图所示
运行完后结果如下图所示,也是负的变成了正的,结果还是 086325h
如果使用宏指令,结果是一样的。输入的数分别是 12h,32h,-12h 和 23h,11h,21h
程序完成后,寄存器里的数成为 12h,32h,12h 和 23h,11h,21h 结果是 334335h
六、 实验用程序清单(要有注释)
实验 4(是否存在 100 这个数)
15H,0DH,64H,60H,62H
DSEG
DATA
CNT DW
DSEG
SSEG
SKTOP
SSEG
CSEG
SEGMENT
DB
05
ENDS
SEGMENT STACK
DB
20 DUP(0)
ENDS
SEGMENT
ASSUME
;栈段
;代码段
CS: CSEG, DS: DSEG ,SS:SSEG
START: MOV AX, DSEG
MOV DS, AX
LEA SI,DATA
MOV CX,CNT
XOR AX,AX
;将数据的首地址送到 si 里
;将数据个数送到 CX 中
;将 AX 清零
AGAIN: MOV AL,[SI]
;将第一个数赋给 AL
;与 64H 比较
;若相等,则直接转到 disp1,输出 y
;若不相等,看下一个数据,且循环
;若 5 个数据跟 64H 都不等,则输出 N
AGAIN
DISP1
CMP AL,64H
JZ
INC SI
LOOP
MOV DL,'N'
MOV AH,02H
INT 21H
JMP STOP
DISP1: MOV DL,'Y'
MOV AH,02H
INT 21H
STOP:
MOV AH,4CH
INT 21H
CSEG
ENDS
END START
若换成数据串操作指令
15H,0DH,64H,60H,62H
DSEG
DATA
CNT DW
DSEG
SSEG
SKTOP
SSEG
CSEG
SEGMENT
DB
05
ENDS
SEGMENT STACK
DB
20 DUP(0)
ENDS
SEGMENT
ASSUME
;栈段
;代码段
CS: CSEG, DS: DSEG ,SS:SSEG
START: MOV AX, DSEG
MOV DS, AX
LEA SI,DATA
MOV CX,CNT
XOR AX,AX
CLD
;指针地址增 1
AGAIN: LODSB
;使用 LODSB 指令,简化程序,LODSB 就相当于 AL<---DS:[SI],SI<---SI+1
CMP AL,64H
JZ
DISP1
AGAIN
LOOP
MOV DL,'N'
MOV AH,02H
INT 21H
JMP STOP
DISP1: MOV DL,'Y'
MOV AH,02H
INT 21H
STOP:
MOV AH,4CH
INT 21H
CSEG
ENDS
END START
实验 5(输出 99 乘法表)
DSEG
DATA
DSEG
CSEG
DISP
0
SEGMENT
DB
ENDS
SEGMENT
ASSUME
PROC
AX
CX
DX
BX
PUSH
PUSH
PUSH
PUSH
XOR CX,CX
MOV BX,10
S: XOR DX,DX
数是 dx
DIV BX
INC CX
PUSH
cmp ax,0
jne s
dx
CS:CSEG,DS:DSEG
;子程序的功能是输出两数相乘的结果
;以下四句保存各个寄存器的值
;初始化 cx=0,cx 记录数的位数
;初始化 bx=10,bx 作为除数
;初始化 dx=0,因为以下的除法是 16 位操作数,所以被除
;而参数是 ax,所以务必清 dx 为 0
;位数加 1
;保存余数
;若 ax=0,则结束
;否则继续循环 s
s1: pop DX
;以下 5 句是逆向取出被保存的余数,并显示
S1
ADD DL,30H
MOV AH,02H
INT 21H
LOOP
POP BX
POP DX
POP CX
POP AX
RET
;以下 4 句是恢复各个寄存器的值
;返回
DISP
ENDP
START: MOV AX,DSEG
MOV DS,AX
MOV BX,1
MOV CX,1
S0: MOV DL,BL
;以下 4 句是以 10 进制显示 bl
ADD DL,30H
MOV AH,02H
INT 21H
MOV DL,'*'
MOV AH,02H
INT 21H
MOV DL,CL
ADD DL,30H
INT 21H
MOV DL,'='
INT 21H
MOV AX,BX
MOV AL,BL
MUL CL
CALL
DISP
MOV DL,20H
MOV AH,02H
INT 21H
INC CX
CMP CX,BX
JLE S0
MOV DL,0DH
MOV AH,02H
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
MOV CX,1
INC BX
CMP BX,10
JB
S0
;显示*号
;以下 3 句以 10 进制显示 cl
;显示=号
;以下 3 句完成 ax=bl*cl
;调用 disp 函数以 10 进制显示 ax 里的结果
;输出一个空格
;以下 3 句检测 cx 是否大于 bx,若真进入下一行
;以下 6 句输出回车
;还原 cx=1
;更新 bx
;bx>9 则结束
;否则继续
MOV AH,4CH
INT 21H
ENDS
CSEG
END START
实验 6(使用子程序的)
13h,22h,-6h
12h,41h,2h
segment
Db
Db
3
dup(?)
ends
segment stack
20 DUP(?)
ends
Dseg
DATA1
DATA2
LEN Dw
SUM Db
dseg
sseg
SK DB
sseg
CSEG
;定义数据段
;测试数据
;数据长度
;和
;定义堆栈段
;堆栈段结束
;定义代码段
segment
assume
assume
MODULUS PROC
MOV CX,LEN
cs:CSEG,ds:dseg
ss:sseg
;求绝对值
AGAIN1: MOV AL,[SI]
;取数据
AL,AL
OR
JS
Z
JNS F
Z: mov dL,0
sub dL,[si]
MOV [SI],DL
F: INC SI
AGAIN1
LOOP
RET
MODULUS ENDP
;负数,跳转 Z
;正数,跳转 F
;负数的话,用 0 减去这个数,
;再把结果返回到[SI]中
;取下个数据
SUM1
PROC
;数据求和
MOV CX,LEN
MOV DI,OFFSET SUM
CLC
AGAIN2: MOV AL,[SI]
;取数据
MOV BL,[DI]
ADC BL,AL
MOV [DI],BL
ADD SI,1
ADD DI,1
;相加,求和
;存入 SUM 单元中
;取下个数据