IBM-PC 汇编语言程序设计复习

期末复习汇编…真的是好努力的复习…
实验老师让我们做的那几个实验,想想还觉得谢谢了~
谈一下输入输出、分支流程、基本指令,再谈一下做过的几个题目。

输入输出

整数的ASCII码值转为数值

  • 0-9 30H-39H
    可以减去 30H 或者 与上 1111(15)
  • A-F 41H-46H
    减去 37H(55)
  • a-z 61H-66H
    减去 57H(75)

输入一位十六进制整数

1
2
3
4
5
6
7
8
IN_1_HEX:
MOV AH, 01H
INT 21H ;输入的值存在AL里
CMP AL, '9' ;输入的值在内存中都是以ASCII码的值表示
JBE IN
SUB AL, 07H
IN:
SUB AL, 30H

输入两位十六进制整数

两位十六进制表示的值最多是 FF ,也就是 255,用八位就可以存下。

1
2
3
4
5
6
7
IN_2_HEX:
CALL IN_1_HEX ;高位十六进制->AL
MOV AH, 10H
MUL AH
MOV AH, AL
CALL IN_1_HEX ;低位十六进制->AL
ADD AL, AH

输入一位十进制整数

实际使用的时候记得要保护之前的数据,先 PUSH 再 POP

1
2
3
4
IN_1_DEC:
MOV AH, 01H ;AL
INT 21H
SUB AL, 30H

输入两位十进制整数

1
2
3
4
5
6
7
IN_2_DEC:
CALL IN_1_DEC
MOV AH, 10 ; 十六进制这里为10H
MUL AH
MOV AH, AL
CALL IN_1_DEC
ADD AL, AH

输出一位十六进制整数

1
2
3
4
5
6
7
8
9
DISP_1_HEX:
CMP DL, 09H
JBE L1
ADD DL, 07H
L1:
ADD DL, 30H

MOV AH, 02H
INT 21H

输出两位十六进制整数

1
2
3
4
5
6
7
8
9
DISP_2_HEX:
MOV AL, DL
MOV AH, 0
MOV DL, 10H
DIV DL ; 除数是 8 位 AL 存商, AH 存余数
MOV DL, AL
CALL DISP_1_HEX
MOV DL, AH
CALL DISP_1_HEX

输出一位十进制整数

1
2
3
4
5
6
7
DISP_1_DEC:
PUSH AX
ADD DL,30H
MOV AH,02H
INT 21H
POP AX
RET

输出两位十进制整数

1
2
3
4
5
6
7
8
9
10
11
12
DISP_2_DEC:    ; DL 除十取余法
PUSH AX
MOV AL,DL
MOV AH,0
MOV DL,10
DIV DL ; 除数是 8 位 AL 存商, AH 存余数
MOV DL,AL
CALL DISP_1_DEC
MOV DL,AH
CALL DISP_1_DEC
POP AX
RET

带符号位的输出多位十进制整数

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
DISP:            ; 用十进制出AX中的数
PUSHF
PUSH DX
PUSH AX
PUSH BX
PUSH CX

MOV CX, 0
MOV BX, 10 ; 除 10 取余法

TEST AX, 8000H ; 检测AX首位是1还是0
JE DISP1 ; 如果上一句的结果为0,就跳
CALL FF ; 输出负号
NEG AX ; 取反+1

DISP1:
MOV DX, 0
DIV BX ;除数是 16 位 AX,商;DX,余数
PUSH DX
INC CX
OR AX, AX ; 是否商完
JNE DISP1 ; 没商完继续商

DISP2:
POP DX
ADD DL, 30H ; 以ascii码输出
MOV AH, 02H
INT 21H
LOOP DISP2

POP CX
POP BX
POP AX
POP DX
POPF
RET
FF:
PUSH DX
PUSH AX

MOV DL, '-'
MOV AH, 02H
INT 21H

POP AX
POP DX
RET

循环分支结构

比较

最重要的就是 比较 了,
TEST,AND,CMP,SUB 还有等等等等…都可以拿来做比较。

TEST 指令

指令格式: TEST DST, SRC
TEST 指令可以被用来检测某一位是否为 1,因为其本质就是与运算,也就是 DST & SRC,但是不改变源操作数和目标操作数。
00010000 & X 的结果就表示 X 的倒数第五位是否为 1,要是与出来为 0,就说明这一位为0,否则为1。

CMP 指令

指令格式:CMP DST, SRC
可以比较两个数的大小,本质就是减法运算,也就是 DST - SRC,但是不改变源操作数和目标操作数。

跳转指令

这里的就是判断被比较的两个数的具体大小,然后决定执行哪一句。
C-style 的语言中是这样:

1
2
3
4
5
if (a > b){
// a > b 的话执行这儿
}else{
// a <= b 的话执行这儿
}

汇编中呢,就是:

1
2
3
4
5
  CMP AX, BX
JA AGB
# AX <= BX 的话执行这儿
AGB:
# AX > BX 的话执行这儿

上面的 JA 就是一个跳转指令,再详细的各种指令我就不说了,看书~
下面稍微说几个记得牢的~

  • JE 两个数相等
  • JNE 两个数不相等
  • JA 无符号 前者大于后者
    我是这样记得, A 就是两个比较的数里前面那个,B 就是两个比较的数里后面那个,所以 JA 就是前面的大。
  • JG 有符号比较,前者大于后者
    G 的意思就是 greater than
  • JB 无符号 前者小于后者
  • JL 有符号比较 前者小于后者
    L = less than
  • JAE 无符号大于等于
  • JGE 有符号大于等于
  • JBE 无符号小于等于
  • JLE 有符号小于等于

二进制转十六进制

我们都知道,一位十六进制可以表示四位二进制,所以要把二进制转为十六进制的画,得每四位每四位的转换。
大概流程如下

1
2
3
4
5
6
7
8
digraph g {
循环左移四位二进制
-> 取低四位
-> "低四位+30H"
-> 输出低四位;

输出低四位 ->循环左移四位二进制 [label="如果位数不为0"]
}

控制转移指令

书上P85

题目

输入二十位带符号十六进制数,排序后输出十进制最大数、最小数、次大数、次小数

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
DATA SEGMENT
X DW 20 DUP(?)
NUM DW 6
DATA ENDS
S1 SEGMENT PARA STACK
BUF1 DW 20H DUP (0)
LEN1 EQU $-BUF1
S1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:S1
GO:
MOV AX,DATA
MOV DS,AX
MOV AX,S1
MOV SS,AX
MOV SP,LEN1

MOV CX,NUM
MOV SI,OFFSET X

L1:
CALL IN_2_HEX
MOV AH, AL
CALL IN_2_HEX
MOV [SI],AX
CC:
CALL SPACE
ADD SI,2
LOOP L1
CALL HR
MOV CX,NUM
MOV SI,OFFSET X
DEC CX

LOOP1:
PUSH CX
MOV BX,OFFSET X
LOOP2:
MOV AX,[BX]
CMP AX,[BX+2]
JGE CONTINUE ;有符号比较
XCHG AX,[BX+2]
MOV [BX],AX
CONTINUE:
ADD BX,2
LOOP LOOP2
POP CX
LOOP LOOP1
MOV cx, NUM
MOV si,offset X
CALL HR

dispdec2:
MOV AX,[si]
call DISP
call SPACE
add si,2
loop dispdec2
CALL HR

MOV si,offset X
CALL HR

; 最小数
DEC NUM
SHL NUM, 1
ADD SI,NUM
MOV AX,[SI]
call DISP
call SPACE

; 最大数
MOV si,offset X
MOV AX,[si]
call DISP
call SPACE

; 次小数

ADD SI,NUM
MOV AX,[SI-2]
call DISP
call SPACE

; 次大数
MOV si,offset X
MOV AX,[SI+2]
call DISP
call HR

MOV AH,4CH
INT 21H

IN_2_HEX:
PUSHF
PUSH BX
MOV BH,AH
CALL IN_1_HEX ;AL high
MOV AH,10H
MUL AH ;
MOV AH,AL
CALL IN_1_HEX ;AL low
ADD AL,AH
MOV AH,BH
POP BX
POPF
RET

IN_1_HEX:
PUSHF
PUSH BX
MOV BH,AH

MOV AH,01H
INT 21H

cmp AL,'9'
JBE IN_B
SUB AL,07H
IN_B: ; 'A-F'
SUB AL,30H
MOV AH,BH
POP BX
POPF
RET


DISP:
PUSHF
PUSH DX
PUSH AX
PUSH BX
PUSH CX

MOV CX,0
MOV BX,10

test AX,8000H;是否为负
JE DISP1
CALL FF
;AND AX,7FFFH
NEG AX

DISP1:
MOV DX,0
DIV BX ;AX,商;DX,余数
PUSH DX
INC CX
OR AX,AX ;是否为0
JNE DISP1
DISP2:
MOV AH,2
POP DX
ADD DL,30H
INT 21H
LOOP DISP2
POP CX
POP BX
POP AX
POP DX
POPF
RET


SPACE:
PUSH DX
PUSH AX
MOV DL,20H
MOV AH,02H
INT 21H
POP AX
POP DX
RET

HR:
PUSH AX
PUSH DX
MOV AH,02H
MOV DL,0AH
INT 21H
MOV DL,0DH
INT 21H
POP DX
POP AX
RET
FF:
PUSH DX
PUSH AX
MOV DL,'-'
MOV AH,02H
INT 21H
POP AX
POP DX
RET
CODE ENDS
END GO
- 正文到此结束啦 -
  • 文章作者: Artin
  • 文章标题: IBM-PC 汇编语言程序设计复习
  • 文章标题: https://lengthmin.me/posts/assembler-basic/
  • 更新时间: 2019-08-25, 20:02:59
  • 更新历史: Blame, History 源文件: .md Raw
  • 版权声明: 署名-非商用-相同方式共享 4.0 转载请保留原文链接及作者。