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
300
301
302
303
304
305
|
section .text
align 4
global kmain
global interrupt_handler
extern idt_init
extern pio_read
extern pio_write
interrupt_handler:
mov ebx, [esp + 34]
shr ebx, 16
cmp ebx, 0x21
je .int21
jmp .end
.int21:
cmp ah, 0x1
je .int21.kprint
jmp .end
.int21.kprint:
;sub esp, 4
;mov [esp - 4], bx
;shr bx, 8
;push word bx
;mov bx, [esp - 4]
;and bx, 0xff
;push bx
;call screen_gotoxy
;add esp, 8
push edx
call kprint
add esp, 4
.end:
ret
cursor_move:
push ebp
mov ebp, esp
sub ebp, 4
call screen_getxy
mov [ebp - 4], eax
push 0x3D4
push 14
call pio_write
mov ebx, [ebp + 4]
shr ebx, 8
push 0x3D5
push word [ebx]
call pio_write
push 0x3D4
push 15
call pio_write
mov ebx, [ebp + 4]
push 0x3D5
push word [ebx]
call pio_write
add ebp, 4
leave
ret
screen_fill:
; = purpose
; Fills the screen with a character and color
;
; = stack arguments (order of use)
; push ' ' ; character
; push 0x07 ; color attribute
push ebp
mov ebp, esp
xor eax, eax ; clear eax
mov eax, [ebp + 8] ; get character
shl eax, 8 ; shift character into MSB
or eax, [ebp + 12] ; set color attribute
mov ecx, CONSOLE_SIZE ; use entire screen
mov edi, screen_buffer ; destination = screen_buffer
cld ; will increment esi and edi
rep stosw ; char+color -> screen_buffer
mov esp, ebp
pop ebp
ret
screen_refresh:
push ebp
mov ebp, esp
pusha
mov ecx, CONSOLE_SIZE ; use entire screen
mov esi, screen_buffer ; source = screen_buffer
mov edi, VIDEO_RAM ; destination = video RAM
cld ; will increment esi and edi
rep movsw ; char+color -> screen_buffer
popa
mov esp, ebp
pop ebp
ret
screen_gotoxy:
push ebp
mov ebp, esp
pusha
; y * width + x
mov ebx, CONSOLE_W * 2
mov eax, [ebp + 12]
mul ebx
add eax, [ebp + 8]
mov [screen_pos], eax
popa
leave
ret
screen_getxy:
push ebp
mov ebp, esp
mov eax, [screen_pos]
leave
ret
screen_updatexy:
push ebp
mov ebp, esp
add word [screen_pos], 2
cmp word [screen_pos], CONSOLE_SIZE
call screen_scroll_up
leave
ret
screen_scroll_up:
push ebp
mov ebp, esp
nop
leave
ret
screen_scroll_down:
push ebp
mov ebp, esp
nop
leave
ret
kprint:
; = purpose
; Writes a buffer to the screen
;
; = globals
; kprint_delay: if != 0; echo slowly
;
; = stack arguments (order of use)
; push buffer
push ebp
mov ebp, esp
xor ebx, ebx
xor esi, esi
xor edi, edi
mov esi, [ebp + 8] ; source buffer
mov edi, screen_buffer ; output to screen buffer
mov ebx, [screen_pos] ; get current screen position
add edi, ebx ; move to current screen position
mov ecx, 0xff ; delay counter
.write:
cmp byte [kprint_delay], 0 ; determine if we want a delay
je .nodelay ; if kprint_nodelay == 0:
; nodelay()
; else:
; delay()
.delay:
dec ecx ; while ecx != 0: ecx--
call screen_refresh
jne .delay
.nodelay:
mov ebx, [esi] ; get value from source buffer
mov [edi], bl ; write value to screen buffer
inc esi ; next char in source buffer
add edi, 2 ; skip over screen attribute byte
call screen_updatexy ; update screen_pos
cmp bl, 0 ; if ch != 0: write
jne .write
call screen_refresh ; dump screen buffer to video ram
leave
ret
kputc:
push ebp
mov ebp, esp
mov esi, [screen_pos]
mov edi, screen_buffer
add edi, esi
mov [edi], dl
call screen_updatexy
call screen_refresh
leave
ret
kprintnl:
push ebp
mov ebp, esp
nop
leave
ret
kmain:
push ebp
mov ebp, esp
mov byte [screen_pos], 2 ; Initialize screen position
;call cursor_move
call idt_init
; Fill screen with
push ' ' ; spaces &&
push 0x07 ; white forground on blue background
call screen_fill ; fill the screen buffer
call screen_refresh ; dump screen buffer to video ram
;push 12
;push 30
;call screen_gotoxy
;mov byte [kprint_delay], 1 ; tell kprint to delay writes
push message ; push message address as argument
call kprint ; print message
call kprintnl
mov dl, 'A'
call kputc
mov word [VIDEO_RAM + CONSOLE_SIZE - 6], \
0x4F << 8 | 'I' ; END OF MAIN MARKER
;mov ah, 1
;mov bh, 2
;mov bl, 2
;mov edx, message2
;int 21h ; here goes nothing
mov word [VIDEO_RAM + CONSOLE_SIZE - 6], \
0x2F << 8 | 'I' ; END OF MAIN MARKER
mov word [VIDEO_RAM + CONSOLE_SIZE - 4], \
0x2F << 8 | 'K' ; END OF MAIN MARKER
mov esp, ebp
pop ebp
ret
section .data
%include 'constants.asm'
message: db 'Kernel programming is fun!', 0
message2: db 'This is a test.', 0
section .bss
kprint_delay: resb 1
screen_pos: resd 1
screen_buffer: resb CONSOLE_SIZE
screen_buffer_end:
|