-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathui.asm
299 lines (211 loc) · 5.67 KB
/
ui.asm
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
ui_write_char:
; IN: al: output char
; OUT: the ASCII character in al is printed on the screen
push ax
mov ah, 0Eh ; BIOS putchar routine number
cmp al, `\n` ; Is the character a newline?
je short .newline ; If so, start a new line
int 10h ; Otherwise just draw the character
jmp short .return
.newline:
mov al, `\r`
int 10h ; Move cursor to the beginning of the line
mov al, `\n`
int 10h ; Move cursor down
.return:
pop ax
ret
ui_write_newline:
; IN: N/A
; OUT: a newline is printed on the screen
push ax
mov al, `\n`
call ui_write_char ; Print the newline using ui_write_char
pop ax
ret
ui_write_lim_string:
; IN: si: output string
; IN: cx: output string length
; OUT: the first cx characters of si are printed on the screen
push si
push ax
push cx
.loop:
cmp cx, 0 ; Are there no more chars to be printed?
je short .return ; If so, return
lodsb ; Move [si] to al, then increment si
cmp al, 0
je short .return ; Return if its the end of the string
call ui_write_char ; Print the character in al
dec cx ; Decrement cx, since a character was printed
jmp short .loop
.return:
pop cx
pop ax
pop si
ret
ui_write_string:
; IN: si: output string
; OUT: the NUL terminated string in si is printed on the screen
push ax
push si
.loop:
lodsb ; Move [si] to al, then increment si
cmp al, 0 ; Is is NUL?
je short .return ; If so, return
call ui_write_char ; Otherwise print the character
jmp short .loop ; Proceed to printing the next one
.return:
pop si
pop ax
ret
ui_write_int:
; IN: ax: output integer
; OUT: the integer in ax is printed on the screen
.size equ 7
.string equ 0
push ax
push si
push di
push bp
sub sp, .size
mov bp, sp ; Allocate local variables
mov di, bp
call string_int_to ; Convert ax to a string under bp
mov si, bp
call ui_write_string ; Write the string under bp
.return:
add sp, .size ; Dealloc variables
pop bp
pop di
pop si
pop ax
ret
ui_read_char:
; IN: N/A
; OUT: al: ASCII charater code
; OUT: ah: scan code
mov ah, 10h
int 16h
ret
ui_read_string:
; IN: di: input buffer pointer
; OUT: modified buffer
push ax
push bx
push di
mov bx, di ; Save di in bx for later
.loop:
mov ah, 00h ; Use a bios interrupt to get a char
int 16h
cmp al, `\b` ; If it's a backspace, draw it
je short .backspace
cmp al, `\r` ; If it's an enter, stop reading
je short .return
call ui_write_char ; Show the character on the screen
stosb ; Store the character in the buffer
jmp short .loop
.backspace:
cmp bx, di ; Is the buffer empty?
je short .loop ; If so, don't draw the backspace
mov al, `\b` ; Move the cursor back
call ui_write_char
mov al, ` ` ; Draw a blank space to hide the old char
call ui_write_char
mov al, `\b` ; Move the cursor back again
call ui_write_char
dec di ; Decrement the buffer pointer
jmp short .loop ; Continue reading characters
.return:
mov byte [di], 0 ; NUL terminate the character
call ui_write_newline ; Go to a new line
pop di
pop bx
pop ax
ret
ui_hide_cursor:
; IN: N/A
; OUT: the cursor is invisible
push ax
push cx
mov ah, 1 ; Cursor shape routine number
mov ch, 32 ; Cursor hidden
int 10h
pop cx
pop ax
ret
ui_set_std_cursor:
; IN: N/A
; OUT: the cursor is in the standard underscore form
push ax
push cx
mov ah, 1 ; Cursor shape routine number
mov ch, 6 ; The cursor starts at the height of 6th pixel
mov cl, 7 ; And ends at 7th
int 10h
pop cx
pop ax
ret
ui_set_box_cursor:
; IN: N/A
; OUT: the cursor is in the box-shaped form
push ax
push cx
mov ah, 1 ; Cursor shape routine number
mov ch, 0 ; The cursor starts at the height of zero pixels
mov cl, 7 ; And ends at 7th
int 10h
pop cx
pop ax
ret
ui_move_cursor:
; IN: al: column
; IN: ah: row
; OUT: the cursor is on the al,ah position in the screen
;
; Note that the top-left corner of the screen is (al=0, ah=0).
push ax
push bx
push dx
mov dl, al ; Take the required col from al
mov dh, ah ; Take the required row from ah
mov bh, 0 ; Set screen page number to 0 (current)
mov ah, 2 ; Set BIOS routine number to 2 (move cursor)
int 10h
pop dx
pop bx
pop ax
ret
ui_find_cursor:
; IN: N/A
; OUT: al: column
; OUT: ah: row
push bx
push cx
push dx
mov ah, 03h
mov bh, 0
int 0h
mov ax, dx
pop dx
pop cx
pop bx
ret
ui_clear_screen:
; IN: N/A
; OUT: the screen is cleared
pusha
mov ah, 07h ; Scroll down routine number
mov al, 0 ; al = 0 clears entire window
mov ch, 0 ; Row of window's upper right corner
mov cl, 0 ; Column of window's upper right corner
mov dh, 24 ; Row of window's lower right corner
mov dl, 79 ; Column of window's lower right corner
mov bh, 07h ; The text color will be light gray
mov bl, 00h ; The background color will be black
int 10h
mov al, 0 ; Move cursor to the beginning of the screen
mov ah, 0
call ui_move_cursor
popa
ret