汇编语言弹跳小球

实现功能:

  1. 小球从一点开始运动,碰到边界后反弹
  2. 使用组合键Ctrl + F暂停、继续
  3. 使用组合键Ctrl + X退出

代码

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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
 ; bouncing ball
; masm 5.0
;***************************************************************
data_seg segment

count dw 1 ; count for a update deltatime
count_max equ 1

old_cs1c dw ?
old_ip1c dw ?

origin_x db ? ; cursor original size
origin_y db ?

v_x db 1 ; velocity of ball
v_y db 2 ;

stopped db 0 ; flag of stopped

ball_char equ '*' ; character represents ball
ball_attr equ 0eh ; attribute of ball

x_start equ 4 ; start position
y_start equ 3
x_min equ 1 ; defination of moving area : 0-----> y
x_max equ 20 ; |
y_min equ 1 ; \|
y_max equ 20 ; x

code_ctrl equ 1dh ; defination of key code
code_f equ 21h
code_x equ 2dh
bit_ctrl equ 04h
data_seg ends
;***************************************************************
stack_seg segment stack ; can't omit 'stack'
dw 100 dup(?)
tos label word
stack_seg ends
;***************************************************************
code_seg segment
;--------------------
main proc far
assume cs: code_seg, ss: stack_seg, ds: data_seg, es:data_seg
start:
;setup ss and sp
mov ax, stack_seg
mov ss, ax
mov sp, offset tos
;setup stack for return
;push ds
;sub ax, ax
;push ax
;setup ds and es
mov ax, data_seg
mov ds, ax
mov es, ax
;main code

; save old timer interrupt vector
mov al, 1ch
mov ah, 35h
int 21h
mov old_cs1c, es
mov old_ip1c, bx
push ds
; set new timer interrupt vector
mov dx, offset update
mov ax, seg update
mov ds, ax
mov al, 1ch
mov ah, 25h
int 21h
pop ds
; enable timer and keyboard interrupt
in al, 21h
and al, 11111100b
out 21h, al
sti
; clear screen
call clear_scr

; save cursor original size
mov bh, 0
mov ah, 3
int 10h
mov origin_y, ch
mov origin_x, cl

; hide cursor
mov cx, 80h
mov ah, 1
int 10h

; set cursor position
mov bh, 0
mov dh, x_min - 1 ; row and column
mov dl, y_min - 1
mov ah, 2
int 10h
; draw moving area
mov al, '=' ; character
mov bh, 0 ; page
mov bl, 0dah
mov cx, y_max - y_min + 3
mov ah, 9
int 10h
; set cursor position
mov bh, 0
mov dh, x_max + 1 ; row and column
mov dl, y_min - 1
mov ah, 2
int 10h
; draw moving area
mov al, '=' ; character
mov bh, 0 ; page
mov bl, 0dah
mov cx, y_max - y_min + 3
mov ah, 9
int 10h

; set start position
mov bh, 0
mov dh, x_start ; row and column
mov dl, y_start
mov ah, 2
int 10h

main_loop:

get_ctrl_f:
; get keyboard status
mov ah, 2
int 16h
test al, bit_ctrl ; if pressed ctrl
jz main_loop
; is any key pressed
mov ah, 0bh
int 21h
inc al
jnz main_loop
; get another key
mov ah, 0
int 16h
cmp ah, code_x ; if pressed x => exit
je exit
cmp ah, code_f ; if pressed f => toggle stop
jne main_loop
mov al, 1
xor stopped, al
jmp main_loop

exit:
call clear_scr
; restore old timer interrupt vector
mov dx, old_ip1c
mov ds, old_cs1c
mov al, 1ch
mov ah, 25h
int 21h
; reset cursor
mov ch, origin_y
mov cl, origin_x
mov ah, 1
int 10h
; return
mov ax, 4c00h
int 21h
main endp
;--------------------
update proc near
; frame update
push ds
push ax
push bx
push cx
push dx

mov ax, data_seg
mov ds, ax
sti
cmp stopped, 1
je update_exit
dec count
jnz update_exit
mov count, count_max ; update interval

; clear previous position
mov al, ' '
mov bh, 0 ; page
mov bl, 0 ; attribute
mov cx, 1 ; repeat times
mov ah, 9 ; show char
int 10h

; get current position dh, dl
mov bh, 0 ; page
mov ah, 3 ; get cursor position
int 10h
; calculate next position
cmp dh, x_min
ja no_min_x
neg v_x
no_min_x:
cmp dh, x_max
jb add_x
neg v_x
add_x:
add dh, v_x

cmp dl, y_min
ja no_min_y
neg v_y
no_min_y:
cmp dl, y_max
jb add_y
neg v_y
add_y:
add dl, v_y

; set new cursor position
mov bh, 0
mov ah, 2
int 10h
; show ball
mov al, ball_char
mov bh, 0 ; page
mov bl, ball_attr ; attribute
mov cx, 1 ; repeat times
mov ah, 9 ; show character
int 10h

update_exit:
cli
pop dx
pop cx
pop bx
pop ax
pop ds
iret
update endp
;--------------------
clear_scr proc near
; clear screen
push ax
push bx
push cx
push dx
mov ah, 6 ; scroll up screen
mov al, 0 ; blank screen
mov bh, 7 ; blank line
mov ch, 0 ; upper left row
mov cl, 0 ; upper left column
mov dh, 24 ; lower right row
mov dl, 79 ; lower right column
int 10h
; locate cursor to upper left
mov bh, 0 ; page
mov dx, 0 ; row and column
mov ah, 2 ; locate cursor
int 10h
pop dx
pop cx
pop bx
pop ax
ret
clear_scr endp
;--------------------
code_seg ends
;***************************************************************
end start

效果展示