实验二、循环与子程序程序设计

一、实验目的:

  1. 加深对循环结构的理解。
  1. 掌握循环程序的设计方法。
  2. 学习子程序的定义和调用方法。
  3. 掌握子程序、子程序的嵌套、递归子程序的结构。
  4. 掌握子程序设计、编制及调试。
  5. 熟练掌握DEBUG的常用命令,学会用DEBUG调试程序。

二、实验内容:

  1. 编制程序计算S=1+2·3+3·4+4·5+……+N(N+1)+……直到N(N+1)大于200为止,并将结果由屏幕上显示出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
DATA SEGMENT
BUF DB'S=1+2*3+3*4+4*5+...+N(N+1)+...=','$'
RES DW 4 DUP(0),'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS, AX
MOV DX, OFFSET BUF
MOV AH, 09H
INT 21H
MOV DX, 1
MOV BL, 2
NEXT: MOV AL, BL
INC BL
MUL BL
ADD DX, AX
CMP AX, 200
JNA NEXT
MOV CX, 0004H
MOV DI, OFFSET RES
ADD DI, 03H
NEXT1:MOV AX, DX
AND AX, 000FH
CMP AL, 0AH
JB NEXT2
ADD AL, 07
NEXT2:ADD AL, 30H
MOV [DI],AL
DEC DI
PUSH CX
MOV CL,04
SHR DX,CL
POP CX
LOOP NEXT1
MOV DX, OFFSET RES
MOV AH, 09H
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START
  1. 将从3000H内存单元开始的100个字节存储单元全部清0。
1
2
3
4
5
6
7
8
ORG    2000H
2000 BF0030 MOV DI, 3000
2003 B164 MOV CL, 64
2005 C60500 MOV BYTE PTR[DI],0
2008 47 INC DI
2009 FEC9 DEC CL
200B 75F8 JNZ 2005
200D F4 HLT
  1. 编制在屏幕上显示九九乘法表的程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
STACK SEGMENT   STACK
DB 1024 DUP(0)
STACK ENDS
DATA SEGMENT

BUF DW 0F101H,110DH,52H,100H,456H
COUNT =($-BUF)/2
RESULT DW 4 DUP(?),'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
WDADD PROC
PUSH DI
MOV AX, 0
MOV DX, 0
MOV DI, OFFSET BUF
NEXT2:ADD AX, [DI]
JNC NEXT1
INC DX
NEXT1:ADD DI, 2
LOOP NEXT2
POP DI
RET
WDADD ENDP
SHOW PROC
PUSH CX
PUSH DI
MOV CX, 04H
MOV DI, OFFSET RESULT
MOV BX, AX
ADD DI, 07H
BBB: MOV AX, BX
AND AX, 000FH
CMP AL, 0AH
JB QQQ
ADD AL, 07H
QQQ: ADD AL, 30H
MOV [DI], AL
DEC DI
PUSH CX
MOV CL, 04
SHR BX, CL
POP CX
LOOP BBB
MOV CX, 0004H
CCC: MOV AX, DX
AND AX, 000FH
CMP AL, 0AH
JB DDD
ADD AL, 07H
DDD: ADD AL, 30H
MOV [DI], AL
DEC DI
PUSH CX
MOV CL, 04H
SHR DX, CL
POP CX
LOOP CCC
POP DI
POP CX
RET
SHOW ENDP
BEGIN:MOV AX, DATA
MOV DS, AX
MOV CX, COUNT
CALL WDADD
CALL SHOW
MOV DX, OFFSET RESULT
MOV AH, 09H
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END BEGIN

  1. 编制在屏幕上显示用*组成的三角形的程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
STACK SEGMENT STACK         ;初始化堆栈段
DB 1024 DUP(0)
STACK ENDS ;堆栈段结束

DATA SEGMENT ;定义数据段
I DB 8 ;行数
J DB 1 ;首行字符数
DATA ENDS ;数据段结束

CODE SEGMENT ;定义代码段
ASSUME CS:CODE, DS:DATA ;指明段寄存器与段的关系
BEGIN:
MOV AX, DATA
MOV DS, AX ;装入DS

MOV CL,I
MOV CH,00H ;装入CX作为行数的循环

LOPI:
MOV BL,00H ;外层循环,为行数循环,置BL寄存器为0,作为输出*的计数器
LOPJ:
MOV DL,'*' ;输出一个*
MOV AH,02H
INT 21H

INC BL ;输出一次*,计数器加一
CMP BL,J ;与当前的J(该行*的个数)比较
JNZ LOPJ ;若不等于J则跳回LOPJ继续输出*

INC J ;跳出LOPJ后J加一,为下一行的*个数

MOV DL,0AH ;输出换行符
MOV AH,02H
INT 21H

LOOP LOPI ;(CX)=(CX)-1,若(CX)不等于0则跳回LOPI

MOV AH, 4CH
INT 21H ;程序结束
CODE ENDS
END BEGIN

  1. 设有五个字数据存放在以BUF为首地址的内存单元中,要求采用调用多个字数据相加的子程序方法编程,和的低位字放在RESULT单元,和的高位字放在RESULT+2单元,并将结果显示在屏幕上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
DATA SEGMENT
BUF DW 1234H,3456H,2134H,7893H,3456H
RESULT DW 0,0
DATA ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CODE SEGMENT
ASSUME DS:CODE,SS:STACK,CS:CODE
START: MOV AX,DATA
MOV DS,AX
CALL PLUS_N
MOV SI,OFFSET RESULT
MOV BX,[SI+2]
CALL DISPLAY
MOV BX,[SI]
CALL DISPLAY
MOV AH,4CH
INT 21H
;功能:计算多字节相加
;入口参数:BUF
;出口参数:RESULT
PLUS_N PROC
AND DX,0
AND AX,0
MOV CL,5
MOV SI,OFFSET BUF
LOP: ADD AX,[SI]
ADC DX,0
INC SI
INC SI
LOOP LOP
MOV SI,OFFSET RESULT
MOV [SI],AX
MOV [SI+2],DX
RET
PLUS_N ENDP
;功能:显示十六进数
;入口参数:BX
DISPLAY PROC
MOV CH,4
LOP1: MOV CL,4
ROL BX,CL
MOV DL,BL
AND DL,0FH
ADD DL,30H
CMP DL,3AH
JB NEXT
ADD DL,7
NEXT: MOV AH,2
INT 21H
DEC CH
CMP CH,0
JNZ LOP1
RET
DISPLAY ENDP
CODE ENDS
END START
  1. 编写一个递归子程序,计算指数函数Xn的值,其中X,n从键盘输入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
CODE SEGMENT
ASSUME CS:CODE

START: MOV CX,6
MOV BX,5
CALL DIGUIMI
CALL DIGUIAX
MOV AH,4CH
INT 21H
;================================
DIGUIMI PROC NEAR
; cx为幂次,bx为底
; ax 中返回 乘幂
CMP CX,0
JNE @DIGUIMI
MOV AX,1
RET
@DIGUIMI:
DEC CX
CALL DIGUIMI
MUL BX
RET
DIGUIMI ENDP
;=================================
DIGUIAX PROC NEAR
; 递归显示 AX 中的无符号数(10进制)
PUSH BX
PUSH DX
MOV DX,0
MOV BX,10
DIV BX
CMP AX,0
JE @DIGUIAX1
CALL DIGUIAX
@DIGUIAX1:
OR DX,30H
MOV AH,2
INT 21H
POP DX
POP BX
RET
DIGUIAX ENDP
;=================================
CODE ENDS
END START

三、实验设备

PC机一台

四、实验步骤

  1. 按程序流程图编制实验程序。
  2. 输入源程序。
  3. 汇编、连接程序,执行程序,检查结果。
  4. 对内存单元3000H开始的100个存储单元用E命令输入任意数。
  5. 程序的执行可用DEBUG的G命令,也可用T命令单步跟踪执行。
  6. 用D命令检查执行结果。

五、实验展示

这里展示代码和运行结果,为了方便阅读,将代码块放到了实验内容中。

六、实验总结

  1. 主要使用指令
指令 指令功能
mov reg, data reg = data
add reg, data reg = reg+data
sub reg, data reg = reg-data
mul reg ax = ax*reg
div reg 当reg为8位 ah = ax/reg, al = ax%reg

当reg为16位 ax = ax/reg, dx = ax%reg
cmp a, b a == b zf = 1
a != b zf = 0
a < b cf = 1
a >=b cf = 0
a > b cf = 0, zf = 0
a <= b cf = 1, zf = 1
jb tag 当cf = 1, 跳转到 tag
je tag 当 zf = 1, 跳转到 tag
jmp tag 无条件跳转到 tag
  1. 标志位寄存器
寄存器 功能
sf 符号标志位,运算结果为负时为1
cf 进位标志位(无符号数)当向最高位进位或借位时为1
of 溢出标志位(有符号数)当有符号数运算发生溢出时为1
  1. 汇编循环程序的实现
    循环程序由初始化部分、循环部分、调整部分、控制部分组成,有两种方式,一种是先判断在执行,另一种是先执行再判断。两种控制循环的方式:

    • 计数控制循环:一般使用LOOP指令,要先将循环的次数放入CX中,在多重循环的计数控制中要注保存和复原上一次循环的断点信息,在保留和复原时可以使用堆栈进行处理。自认为可以理解为一根盘绕了确定的圈数的绳子,又进入的头,又出去的尾。
    • 条件控制循环:一般使用JMP指令使程序跳到这一段的开头,用CMP在循环中进行比较判断,再根据程序要求,选择适当的转移条件,跳出循环。自认为可以理解为一圆形的导轨,并在导轨上设置一个初口,在符合条件时就在导轨上脱离,否则,将会在导轨上一直的转下去。

    再循环中可以同时使用两者,当即己知循环的次数限制范围,但又要求在符合条件时结束循环时,就要同时使用两者。

附录

  1. 文件列表

    • 8086-8088 汇编语言指令表.pdf
  2. 下载地址


实验二、循环与子程序程序设计
https://flowerdown.org/posts/20221219-161614.html
作者
Unrealfeather
发布于
2022年12月19日
许可协议