分享SCAU汇编实验代码

实验一

计算(859FH*3)+8765H的值 ,并把结果存在存储器数据段偏移量3578H开始的位置

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
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX

; 题目:

; 计算 (859FH * 3) + 8765H的值

; 结果存在存储器数据段偏移量3578H开始的位置

; 此处输入代码段代码
MOV AX,859FH
MOV BX,3
MUL BX
ADD AX,8765H
ADC DX,0
MOV DS:[3578H],AX
MOV DS:[357AH],DX
; 此处输入代码段代码

MOV AH,4CH
INT 21H
CODES ENDS
END START

实验二

判断AX中的年份(无符号整数)是否闰年,是则将0001传送到BX,否则将BX清零(分别用数据1900、2008、1999、2000做测试)

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
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX

; 题目:

; 判断AX中的年份(无符号整数)是否闰年?

; 是则将0001传送到BX,否则将BX清零

; (分别用数据1900、2008、1999、2000做测试)

; 此处输入代码段代码
MOV AX,1900 ; 测试年份
MOV DX,0
MOV CX,AX ; 保存年份
MOV BX,400
DIV BX
TEST DX,DX
JZ L2 ; 整除400 直接跳转L2

MOV AX,CX
MOV DX,0
MOV BX,4
DIV BX
TEST DX,DX
JNZ L1 ; 无法整除4 直接跳转L1

MOV AX,CX
MOV BX,100
DIV BX
TEST DX,DX
JZ L1 ; 整除4 & 整除100 跳转L2
JNZ L2 ; 无法整除100 跳转L1

L1:
MOV BX,0
MOV AH,4CH
INT 21H
L2:
MOV BX,0001H
; 此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START

实验三

将用户输入的四位(测试数据固定四位)十六进制数变成二进制形式输出(所有字母大写,用户输入非法字符则结束)例如用户输入50F0则输出0101000011110000测试数据:50F0,123A

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
76
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
; 题目:

; 将用户输入的四位(测试数据固定四位)

; 十六进制数变成二进制形式输出

; 所有字母大写,用户输入非法字符则结束

; 例如用户输入50F0则输出0101000011110000

; 此处输入代码段代码
MOV BX,0
MOV CH,4 ; 循环次数
INPUT:
MOV AH,01H ; 输入一个字符,ASCII码在AL中
INT 21H
CMP AX,0130H ; 判断是否非法,AX < 0
JL EXIT
CMP AX,0139H ; 判断是否数字
JLE L1 ; 是数字,跳转L1
CMP AX,0141H ; 判断是否非法,9 < AX < A
JL EXIT
CMP AX,015AH ; 判断是否非法,AX > Z
JNLE EXIT
SUB AL,07H ; 要把A当成数字10,减去A与9中间的差值

L1:
SUB AL,30H ; 把ASCII码转换为数字
MOV CL,4
SHL BX,CL ; BX每次左移4位
ADD BL,AL ; 将数字加到BX中
DEC CH ; 循环次数减一
CMP CH,0 ; 判断循环是否结束
JNZ INPUT ; 循环未结束,跳回

;处理结束,输出换行符
MOV DL,10
MOV AH,02H
INT 21H

MOV CH,16 ; 循环计数器,用来输出16位二进制数
L2:
SHL BX,1 ; BX左移1位,暂存到CF中
JC SET1 ; 若CF为1,则跳转到SET1标签
MOV DL,30H ; 若CF为0,则DL存'0'
JMP PRINT ; 跳转到PRINT标签,输出DL中的字符

SET1:
MOV DL,31H ; CF为1,则DL存'1'

PRINT:
MOV AH,02H ; 输出字符
INT 21H
DEC CH ; 循环次数减一
CMP CH,0 ; 判断循环是否结束
JNZ L2 ; 循环未结束,跳回

EXIT:
MOV AH,4CH
INT 21H
;此处输入代码段代码
CODES ENDS
END START

统计长度为N的字数组ARRAY中有多少种不同数值,例如数组{1,1,3,5,5}中有三种不同数值。将结果存放进BX测试数据:{1,1,3,5,5}{4,2,5,2,5,4,6,7,4,6,9,11,15,9}

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
DATAS SEGMENT
;此处输入数据段代码
FRONT LABEL WORD
ARRAY DW 4, 2, 5, 2, 5, 4, 6, 7, 4, 6, 9, 11, 15, 9
BACK LABEL WORD
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
; 题目:

; 编写程序,统计长度为N的字数组ARRAY中有多少种不同数值

; 例如: 数组{1,1,3,5,5}中有三种不同数值,将结果存放进BX

; 测试数据:{1,1,3,5,5}

; {4,2,5,2,5,4,6,7,4,6,9,11,15,9}

; 此处输入代码段代码
MOV BX,0 ; 初始化计数器
LEA DX,FRONT
LEA CX,BACK
SUB CX,DX ; CX记录数组长度
MOV SI,0
L1: ; 第一层循环
MOV DX,ARRAY[SI] ; DX暂存a[i]
MOV DI,0
L2:
CMP DI,SI ; 表示i==j
JZ ANS ; 跳转ANS
MOV AX,ARRAY[DI] ; AX暂存a[j]
CMP AX,DX ; 比较a[i],a[j]
JE NEXTL2 ; 表示a[i]==a[j],跳转NEXTL2
ADD DI,2 ; j++
JMP L2 ; 继续内层循环
ANS:
INC BX
NEXTL2:
ADD SI,2
CMP SI,CX
JB L1
; 此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START

实验四

若数据段定义

1
2
3
4
data segment
array1 dw 11,22,3BH,4,35,100,12,27,78,24
sum dw ?
data ends

求数组array1中所有 偶数 的和,存放在sum中。测试时除了以上数据外,还需测试以下array1array1 dw 5,128,34,77,22,301,89,64,50,66

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
DATAS SEGMENT
array1 dw 11,22,3BH,4,35,100,12,27,78,24
sum dw ?
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
; 题目:

; 若数据段定义
; data segment
; array1 dw 11,22,3BH,4,35,100,12,27,78,24
; sum dw ?
; data ends
; 求数组array1中所有 偶数 的和,存放在sum中。
; 测试时除了以上数据外,还需测试
; array1
; array1 dw 5,128,34,77,22,301,89,64,50,66

;此处输入代码段代码
MOV SI,0
MOV CX,10 ; 循环次数
MOV DX,0 ; 初始化累加器
L1:
MOV AX,array1[SI]
TEST AX,1 ; 测试奇偶性
JNZ ODD ; 奇数跳转
ADD DX,AX ; 偶数累加
ODD:
ADD SI,2 ; 指针加2
LOOP L1 ; cx≠0,循环继续
MOV sum,DX ; 循环结束,结果存在sum中
;此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START

将AX中数据的二进制形式倒置,并以二进制形式输出。例如0000000011110001,倒置后为1000111100000000(测试数据为1234H,5678H,00FFH,无需做输入,直接在程序中修改测试数据,需要做输出)

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
DATAS SEGMENT
; 此处输入数据段代码
DATAS ENDS

STACKS SEGMENT
; 此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
; 题目:

; 将AX中数据的二进制形式倒置,并以二进制形式输出。

; 例如0000000011110001,倒置后为1000111100000000

; 测试数据为1234H,5678H,00FFH

; 无需做输入,直接在程序中修改测试数据,需要做输出

; 此处输入代码段代码
MOV AX,1234H
MOV CX,2 ; 除数2
MOV BX,16 ; 计数器,记录未输出位数
L1:
XOR DX,DX ; 清空DX
DIV CX ; 除以2,相当于取出末位
CALL PRINT ; 调用打印函数
CMP AX,0 ; 检查是否为0
JNZ L1 ; 不为0,继续循环

MOV CX,BX ; 剩余位数皆为0,存到CX作循环输出

L2:
MOV DX,0 ; DX置0
ADD DX,30H ; 转换为ASCII码
MOV AH,2 ; 调用21号中断的2号功能,输出DX中字符
INT 21H
LOOP L2 ; CX≠0继续循环

MOV AH,4CH ; =退出
INT 21H
PRINT:
PUSH AX ; 压栈保存AX,DX
PUSH DX
ADD DX,30H ; 转换为ASCII码
MOV AH, 2 ; 调用21号中断的2号功能,输出DX中字符
INT 21H
POP DX ; 出栈恢复AX,DX
POP AX
DEC BX ; 已输出1位,计数器减1
RET
; 此处输入代码段代码
CODES ENDS
END START

用户输入四位十六进制数(固定四个字符,如“A123” ”0035”“123f”, 字母可能大写或小写,输入非法字符则退出),在屏幕输出其十进制形式。

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
DATAS SEGMENT
bin dw 10 dup(?) ;存放二进制结果
buf db 5 dup(?) ;存放十进制数 各个数位上的数值 如100,存放为 1,0,0
msg1 db 'please input a hex number',13,10,'$'
msg2 db 'the dec number:',13,10,'$'
crlf db 13,10,'$' ;回车换行
DATAS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
START:
MOV AX,DATAS
MOV DS,AX

mov bx,0 ;初始化bx


input:
mov ah,1 ;输入一个字符
int 21h

sub al,30h ;把al中的ascii码转换成数值
jl init

cmp al,10 ;输入的数在0-9之间跳转
jl toBin

ADD AL,30H
CMP AL,41H
JL EXIT
CMP AL,46H
JNLE L1
ADD AL,20H

L1:
SUB AL,30H

sub al,27h ;再转换为a-f
cmp al,0ah ;输入的字符比a小
jl init ;结束输入
cmp al,10h ;输入的字符比f大
jge init ;结束输入

toBin: ;转换为二进制,把输入组合成意义上的数值
mov cl,4
shl bx,cl ;bx左移4位
mov ah,0
add bx,ax ;把输入后并从ascii码转换来的值与bx相加
mov bin,bx ;转换成二进制数后存到内存bin
jmp input ;继续输入

init: ;初始化,准备转换
mov ax,bin
mov bx,10
mov si,4 ;循环四次,最大到万位

toDec: ;转为各个数位上的数值,如100转换为1,0,0 百位为1...
mov dx,0
div bx ;除10法得到各个位上的数值
mov [buf+si],dl ;余数为该位上的值,第一次循环为个位,第二次为十位...;存到内存中
dec si
cmp ax,0 ;商是否为0,为0算法结束
ja toDec





output: ;输出内存中存放的各个数位上的数值
inc si
mov dl,[buf+si]
add dl,30h ;转为ascii
mov ah,2
int 21h
cmp si,4
jb output


mov ah,1
int 21h
MOV AH,4CH
INT 21H

EXIT:
MOV AH,4CH
INT 21H

CODES ENDS
END START

实验五

在屏幕上输出2-100之间的所有素数(源程序里要求用到子程序判断是否素数,以及用子程序输出十进制整数,要有计算过程,不可以直接抄结果输出)

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
76
77
78
79
80
81
82
83
84
85
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
; 问题

; 在屏幕上输出2-100之间的所有素数

; 源程序里要求用到子程序判断是否素数,以及用子程序输出十进制整数

;此处输入代码段代码
MAIN PROC FAR
MOV AX,DATAS
MOV DS,AX
MOV CX,1 ; 计数器,1 < CX <100
L1:
INC CX ; i++
MOV AX,CX ; 将CX存到AX中
PUSH CX ; CX压栈
CALL IS_PRIME ; 判断是否素数
POP CX ; CX出栈
CMP BX,0 ; 判断素数标志位
JZ L2 ; 非素数,不打印
CALL PRINT ; 素数,打印

L2:
CMP CX,100 ; 判断CX < 100
JL L1 ; < 继续循环
MOV AH,4CH ; 退出
INT 21H

MAIN ENDP

IS_PRIME PROC NEAR
PUSH AX ; AX压栈
MOV BX,1 ; 标志:是否素数
MOV CX,2 ; i 因子
L3:
POP AX ; AX出栈
PUSH AX ; AX进栈
CMP CX,AX ; 判断CX是否 < AX
JE PRIME ; CX == AX
MOV DX,0 ; 清空DX
DIV CX ; 除因子
CMP DX,0 ; 判断能否整除
JE NOT_PRIME ; 能整除不是素数

INC CX ; 因子++
JMP L3 ; 继续循环

NOT_PRIME:
MOV BX,0 ; 不是素数,置标志为0

PRIME:
POP AX
RET ; 返回
IS_PRIME ENDP



PRINT PROC NEAR
MOV BL,10
DIV BL ; 除10
MOV BX,AX ; BX暂存AX内容
MOV AH,02H
MOV DL,BL ; 打印 商(即十位数)
ADD DL,30H ; +'0'
INT 21H
MOV DL,BH ; 打印 余数(即个位数)
ADD DL,30H
INT 21H
MOV DL,' ' ; 打印空格
INT 21H
RET
PRINT ENDP
;此处输入代码段代码
CODES ENDS
END START

编写程序,将数据段里的某数组在原位置逆序(例如ARRAY数组{1,2,3}变为{3,2,1},但首地址依然是ARRAY),要求用子程序实现逆序操作。子程序要求有一定通用性,能够处理不同数组。

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
76
77
78
79
DATAS SEGMENT
ARY DW 1,2,3
ARY_SIZE EQU ($-ARY)/2 ; 数组长度
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
; 问题

; 编写程序,将数据段里的某数组在原位置逆序
; 例如ARRAY数组{1,2,3}变为{3,2,1},但首地址依然是ARRAY
; 要求用子程序实现逆序操作。


;此处输入代码段代码

MOV AX,OFFSET ARY
PUSH AX
MOV AX,OFFSET ARY_SIZE
PUSH AX

CALL REVERSE ; 调用逆序子程序

MOV AH,4CH ; 退出
INT 21H

REVERSE PROC NEAR
PUSH BP
MOV BP,SP

PUSH AX
PUSH CX
PUSH SI
PUSH DI

LEA AX,ARY ; 加载ary首地址到ax
MOV SI,AX
MOV CX,ARY_SIZE ; cx=ary[size]

MOV DI,SI
MOV AX,CX
MOV BL,2
MUL BL
ADD DI,AX
;数组的尾地址的下一个地址
SUB DI,2 ; 现在指向数组的尾地址

L1:
CMP CX,0
JLE OVER

MOV AL,[SI]
XCHG AL,[DI]
MOV [SI],AL

INC SI
DEC DI
LOOP L1


OVER:
POP DI
POP SI
POP CX
POP AX
POP BP
RET 6

REVERSE ENDP

CODES ENDS
END START

编写程序,寻找一个数组里的最大值。其中查找最大值的过程使用子程序,参数传递使用堆栈。

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
DATAS SEGMENT
; 定义数据段,存储数据
ARRAY DW 2,3,4,10
BACK LABEL WORD ; 定义一个字大小的标签
DATAS ENDS

STACKS SEGMENT
; 定义堆栈段
STACKS ENDS

CODES SEGMENT
; 定义代码段
ASSUME CS:CODES,DS:DATAS,SS:STACKS ; 定义段寄存器

START:
MAIN PROC FAR
MOV AX,DATAS
MOV DS,AX

MOV AX, OFFSET ARRAY
; 将数组ARRAY的偏移地址加载到AX中(第一个元素的地址)
PUSH AX
; 将数组ARRAY的偏移地址压入堆栈(第一个元素的地址)
MOV AX, OFFSET BACK
; 将数组BACK的偏移地址加载到AX中(最后一个元素的地址)
PUSH AX
; 将数组BACK的偏移地址压入堆栈(最后一个元素的地址)
CALL FINDMAX
; 调用名为FINDMAX的子程序

MOV AH,4CH
INT 21H
RET
MAIN ENDP

; 用于查找数组中的最大值
FINDMAX PROC NEAR
MOV BP,SP
; 将栈指针加载到BP寄存器中
MOV SI,[BP+4]
; 将堆栈中第一个参数的偏移地址加载到SI中(数组的第一个元素的地址)
MOV DI,[BP+2]
; 将堆栈中第二个参数的偏移地址加载到DI中(数组的最后一个元素的地址)
MOV AX,[SI]
; 将AX加载为数组的第一个元素的值
ADD SI,2
L1:
CMP SI,DI
; 比较SI和DI,检查是否已经遍历完整个数组
JNB OVER
; 如果SI大于等于DI(已经到达数组末尾),则跳转到OVER
CMP AX,[SI]
; 比较AX(当前最大值)和[SI](当前元素的值)
JNB NEXT
; 如果AX大于等于[SI],则跳转到NEXT
MOV AX,[SI]
; 更新AX为[SI]的值(新的最大值)
NEXT:
ADD SI,2
; 移动到数组的下一个元素
JMP L1
; 跳回L1,继续遍历数组
OVER:
RET 4
; 从子程序返回,从堆栈中弹出4个字节
FINDMAX ENDP

CODES ENDS
END START

实验六

在屏幕上输出字符串“welcome to asm”,要求逐个字符输出,每隔约0.5秒左右(可以有0.05秒内的误差)输出一个字符。

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
76
77
DATAS SEGMENT
;此处输入数据段代码
STRING DB 'welcome to asm',0dh,0ah,'$' ; 0DH,0AH 回车,换行
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS

MS1 = 325 ; 1ms延时

START:
MOV AX,DATAS
MOV DS,AX
; 问题

; 在屏幕上输出字符串“welcome to asm”

; 要求逐个字符输出,每隔约0.5秒左右(可以有0.05秒内的误差)输出一个字符

;此处输入代码段代码

MOV CX,14 ; 字符串长度
MOV BX,0 ; 计数器BX
LEA DX,STRING ; STRING的地址存在DX
CALL PRINT ; 打印字符串


MOV AH,4CH
INT 21H

PRINT PROC
L1:
MOV DL,[STRING+BX] ; 字符加载到DL中
MOV AH,02H ; 输出
INT 21H
INC BX ; 计数器+1

PUSH CX
PUSH DX

MOV AL,1 ; 设置延时1次
CALL TIME ; 调用延时程序

POP DX
POP CX


LOOP L1
RET
PRINT ENDP


;延时0.5s子程序
TIME PROC
S0:
MOV CX,500 ; 内循环延时约1ms,外循环500次,则内循环一轮为0.5s
S1:
MOV DX,MS1 ; 延时次数计数
S2:
DEC DX ; 第一层循环 1ms
JNZ S2

DEC CX ; 第二层循环 0.5s
JNZ S1

DEC AL
JNZ S0

RET
TIME ENDP

CODES ENDS
END START

实现秒表,即从0秒开始进行计时,随着时间经过变更显示的秒数(例如经过10秒则显示10,最多100秒。可以有0.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
DATAS SEGMENT
;此处输入数据段代码
COUNTER DB 0
COUNTER1 DB 0
COUNTER2 DB 0
TIME EQU 60000 ; 延迟计数器的值,根据实际需要调整

DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX

; 问题

; 实现秒表,即从0秒开始进行计时,随着时间经过变更显示的秒数

; 例如经过10秒则显示10,最多100秒。可以有0.1秒以内的误差。

; 提示:变更已显示的内容可以清屏后重新显示,清屏可以用

; MOV AX,3

; INT 10H

;此处输入代码段代码
MOV AX, 3 ; 清屏
INT 10H
MOV BX, 0

L2: ; 百位
MOV DL, [COUNTER2]
ADD DL, '0' ; 转换ASCII码
MOV AH, 02H
INT 21H ; 显示字符

L1: ;十位
MOV DL, [COUNTER1]
ADD DL, '0' ; 转换ASCII码
MOV AH, 02H
INT 21H ; 显示字符

L0: ; 个位
MOV DL, [COUNTER] ; 计数器加载到DL
ADD DL, '0' ; 转换ASCII码
MOV AH, 02H
INT 21H ; 显示字符

MOV DI, 30 ; 延迟一段时间
SET_CX:
MOV CX, TIME ; 初始化延迟计数器

DELAY_LOOP:
DEC CX ; 计数器减1
JNZ DELAY_LOOP ; 如果计数器不为0,则继续循环延迟
DEC DI
JNZ SET_CX

INC [COUNTER]
MOV AX, 3 ; 清屏
INT 10H

CMP [COUNTER2], 1 ;检查是否超过100秒
JE RESET_C


CMP [counter], 10 ; 检查计时器0是否超过10秒
JNE L2 ; 如果未超过10秒

CMP [counter], 10
JE C_1

C_1: ;十位进位
INC [COUNTER1]
MOV [COUNTER], 0
CMP [COUNTER1], 10
JE C_2
JMP L2

C_2: ;百位进位
INC [COUNTER2]
MOV [COUNTER1], 0
JMP L2

RESET_C: ;重置时间为000
MOV [COUNTER], 0
MOV [COUNTER1], 0
MOV [COUNTER2], 0
JMP L2

MOV AH,4CH
INT 21H

CODES ENDS
END START

实验七

将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出测试数据:1234,5,7008,66

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
DATA SEGMENT
STRING DB 0DH,0AH,"OVERFLOW!",'$'
DATA ENDS
STACK SEGMENT STACK
DW 100 DUP (?)
TOP LABEL WORD
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
MOV AX,STACK
MOV SS,AX
LEA SP,TOP

MOV BX,0
MOV CX,0 ;统计合法的数字字符个数
MOV SI,10
MOV BP,0 ;符号位默认为0(正数)

MOV AH,7 ;输入第一个字符
INT 21H

CMP AL,0DH ;输入回车,退出
JE EXIT

L1:
CMP AL,'+'
JNE L3 ;不是正号,跳转到L3继续判断
MOV BP,0 ;输入正号,更改符号位

MOV DL,AL ;显示正号
MOV AH,2
INT 21H

JMP L2 ;跳转到L2继续输入数字字符

L2:
MOV AH,7
INT 21H

CMP AL,0DH ;输入回车,跳转到以16进制显示BX
JE PRINT

L3:
CMP AL,30H ;小于30H,继续输入
JB L2
CMP AL,39H ;大于39H,继续输入
JA L2

MOV DL,AL ;显示合法的数字字符
MOV AH,2
INT 21H
INC CX ;合法的数字字符+1

AND DX,0FH ;屏蔽DX高12位
MOV AX,DX

XCHG AX,BX ;交换AX和BX
MUL SI ;AX*10

;数字部分以无符号数输入
;限制数字部分的输入范围0-65535
JC OVERFLOW
ADD BX,AX
JC OVERFLOW

JMP L2 ;无溢出,跳转到L2继续输入数字字符

PRINT:
CMP CX,0 ;判断合法的数字字符个数,CX为0退出
JE EXIT

;接下来判断有符号数的溢出
CMP BP,1
JE NEGATIVE ;判断负数的溢出

CMP BP,0
JE POSITIVE ;判断正数的溢出

NEGATIVE:
NEG BX ;BX是负数,求补
ADD BX,0 ;这条指令会改变PSW,接下来判断符号位
JNS OVERFLOW ;符号位是0,溢出
JMP L4 ;跳转到L4以16进制显示BX

POSITIVE:
ADD BX,0 ;BX是正数
JS OVERFLOW ;符号位是1,溢出

L4:
MOV CX,4

MOV DL,0DH
MOV AH,2
INT 21H

MOV DL,0AH
MOV AH,2
INT 21H

L5:
PUSH CX
MOV CL,4
ROL BX,CL
MOV DL,BL
AND DL,0FH
CMP DL,9
JA L6
ADD DL,30H
JMP L7

L6:
ADD DL,37H
L7:
MOV AH,2
INT 21H
POP CX
LOOP L5

CMP CX,0
JE EXIT

OVERFLOW:
LEA DX,STRING
MOV AH,9
INT 21H

EXIT:
MOV AH,4CH
INT 21H
MAIN ENDP
CODE ENDS
END MAIN

创建文件abc.txt,并由用户输入不超过128个字符保存。创建文件def.txt,将abc.txt中的内容倒置保存(例如,”abcdef”变为“fedcba”,文件位置自定)

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
DATAS SEGMENT
;此处输入数据段代码
FILE1 DB 'abc.txt',0
HANDLE1 DW ?
FILE2 DB 'def.txt',0
HANDLE2 DW ?
BUFFER DB 256 DUP(0)
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AH,3CH ;INT 21H的3CH功能
LEA DX,FILE1 ;DX=ASCIIZ串的首地址
MOV CX,0 ;CX=0,普通文件
INT 21H ;新建文件
JC ERROR ;新建不成功,转ERROR
MOV HANDLE1,AX ;成功,保存文件句柄

READ0:
;读入字符
MOV AH,1
INT 21H
CMP AL,0Dh
JZ L1 ;若是回车则结束
MOV AH,40H
MOV BUFFER,AL
LEA DX,BUFFER
MOV BX,HANDLE1
MOV CX,1
INT 21H
JC ERROR ;写入错误

JMP READ0


L1:
;将FILE1的内容放到BUFFER中
MOV BX,AX
MOV CX,255
MOV DX,OFFSET BUFFER
MOV AH,3FH
INT 21H
JC ERROR

;将BUFFER的内容倒置
MOV SI,0
MOV DI,AX
DEC DI

;倒置操作
LOP1:
CMP SI,DI
JAE NEXT
MOV BH,BUFFER[SI]
MOV BL,BUFFER[DI]
MOV BUFFER[SI],BL
MOV BUFFER[DI],BH
INC SI
DEC DI
JMP LOP1

NEXT:
;创建并打开FILE2文件
MOV DX,OFFSET FILE2
MOV CX,0
MOV AH,3CH
INT 21H
JC ERROR
MOV HANDLE2,AX

;将BUFFER的内容写入FILE2中
MOV BX,HANDLE2
MOV DX,OFFSET BUFFER
MOV CX,255
MOV AH,40H
INT 21H

OVER:
;关闭FILE1文件
MOV BX,HANDLE1
MOV AH,3EH
INT 21H

;关闭FILE2文件
MOV BX,HANDLE2
MOV AH,3EH
INT 21H

ERROR:
MOV AH,4CH
INT 21H


EXIT0:
;关闭文件
MOV AH,3EH
MOV BX,HANDLE1
INT 21H
MOV AH,4CH
INT 21H
CODES ENDS
END START

判断数据段中定义的两个数a和b是否互素(ab均为小于10000的正整数),要求编写子程序完成,采用堆栈传递参数。

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
DATA SEGMENT
a DW ?
b DW ?
g DW ?
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE, DS:DATA

START:
MOV AX, DATA
MOV DS, AX

; 假设a和b的值已经通过某种方式赋值,这里直接赋值用于演示
MOV a, 9
MOV b, 3

; 调用子程序计算最大公约数
MOV AX, a
MOV BX, b
CALL GCD

; 将计算出的最大公约数存储在gcd变量中
MOV g, CX

; 判断是否互素,即gcd是否为1
MOV CX, 1
CMP g, CX
JE MUTUAL_PRIME

; 如果不是互素,可以在这里添加代码处理
JMP END_PROGRAM

MUTUAL_PRIME:
; 如果是互素,可以在这里添加代码处理

END_PROGRAM:
; 结束程序
MOV AH, 4CH
INT 21H

GCD PROC NEAR ; 计算最大公约数的子程序
MOV CX, BX ; 将b的初始值传给CX,作为辗转相除的初始除数
MOV BX, 0

GCD_LOOP:
MOV DX, 0 ; DX用于存放余数

; AX除以CX,商在AX中,余数在DX中
DIV CX

CMP DX, 0 ; 检查余数是否为0
JE GCD_DONE ; 如果余数为0,退出循环

MOV BX, CX ; 将CX的值传给BX,为下一次迭代做准备
MOV CX, DX ; 将余数DX的值传给CX,作为下一次迭代的除数
JMP GCD_LOOP ; 继续循环

GCD_DONE:
RET ; 返回主程序

GCD ENDP

CODE ENDS
END START

实验八

将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出测试数据:1234,5,7008,66

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
76
77
78
79
80
81
82
83
84
85
86
DATAS SEGMENT
STR1 DB 0AH,'Input decimal number: ','$'
STR2 DB 0AH,'hexadecimal number: ','$'
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX

; 问题
; 将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出
; 测试数据:1234,5,7008,66

;此处输入代码段代码

CALL INPUT ; 调用读取
CALL CONVERT ; 调用转换
MOV AH,4CH ; 程序结束
INT 21H

INPUT PROC NEAR
LEA DX,STR1 ; 输出提示字符串
MOV AH,09
INT 21H

LEAGAL1:
MOV AH,01H ; 输入,并在屏幕上显示该字符。
INT 21H

CMP AL,'9' ; 比较输入字符合法性
JA EXIT
CMP AL,'0'
JB EXIT

SUB AL,'0'
MOV AH,0H

MOV DX,AX ; 将新数给 DX
MOV AX,BX ; BX 存的是之前的数要去做乘10运算
MOV BX,DX ; 把新数给 BX 在个位 待会儿直接做加法

MOV CX,0AH ; CX的值是10
MUL CX
ADD BX,AX

JMP LEAGAL1

EXIT:
RET
INPUT ENDP

CONVERT PROC NEAR
LEA DX,STR2
MOV AH,09
INT 21H

MOV CH,04H
MOV CL,04H
LOOPC:
ROL BX,CL
MOV AL,BL
AND AL,0fh
ADD AL,30H
CMP AL,'9'
JBE PRINTF
ADD AL,07H

PRINTF:
MOV DL,AL
MOV AH,2
INT 21H
DEC CH
JNE LOOPC

RET
CONVERT ENDP


CODES ENDS
END START

编写程序,用户输入一个字符串,统计其中数字字符之和并输出,例如输入”1a2b3c”则输出6(假设和不会超过四位数,输入以回车结束)测试数据:1a2b3c, #1abcD0w623v9

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
76
77
78
79
80
81
82
83
DATAS SEGMENT
;此处输入数据段代码
DB 0
NOTE DB 'Please enter the sentence: ',0DH,0AH,'$'
DATAS ENDS

STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX

; 问题
; 编写程序,用户输入一个字符串,统计其中数字字符之和并输出
; 例如输入”1a2b3c”则输出6(假设和不会超过四位数,输入以回车结束)
; 测试数据:1a2b3c, #1abcD0w623v9

;此处输入代码段代码
MOV AH,09H ;输出提示符
MOV DX,OFFSET NOTE
INT 21H

CALL COUNT ;调用统计子程序
CALL print

MOV AH,4CH
INT 21H

COUNT PROC NEAR
INPUT:
MOV AH,01H
INT 21H

CMP AL,0DH
JZ EXIT

CMP AL,'0'
JL INPUT
CMP AL,'9'
JA INPUT

INC BYTE PTR DS:[0]
JMP INPUT

EXIT:
RET
COUNT ENDP

print proc near
mov al,ds:[0]
mov ah,0
mov bx,10
mov cx,0
mov dx,0

legal1:
div bx
push dx
inc cx
cwd
cmp ax,0
jne legal1

legal2:
pop dx
add dl,30h
mov ah,02h
int 21h
loop legal2

mov ah,02h
mov dl,0dh
int 21h

ret
print endp

CODES ENDS
END START