-
Notifications
You must be signed in to change notification settings - Fork 0
/
exception.asm
547 lines (484 loc) · 20.6 KB
/
exception.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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
;#########################################################################
;
;@file exception.asm
;@brief Handlers de excepciones
; Intel x86 compatible en 32 bit.
;@author Agustin Alba Chicar
;@date Octubre, 2015
;@details
;#########################################################################
USE32 ; Modelo de 32 bits
;********************************************************************************
; Simbolos externos y globales
;********************************************************************************
%include "video.inc"
%include "pagination.inc"
GLOBAL exceptionLoadHandlers
GLOBAL exceptionSetNewPagePointer
GLOBAL exceptionSetNewDestinationPointer
;Simbolos de video
EXTERN videoPrint
EXTERN videoClearScreen
;Simbolos de sys_tables
EXTERN GDT32
EXTERN GDTR32
EXTERN nullSelector
EXTERN codeKernelSelector
EXTERN codeUserSelector
EXTERN dataKernelSelector
EXTERN dataUserSelector
EXTERN tssInitSelector
EXTERN tssTask1Selector
EXTERN tssTask2Selector
EXTERN tssSchedulerSelector
EXTERN callKernelGateSelector
EXTERN IDT
;********************************************************************************
; Defines
;********************************************************************************
%define ERROR_CODE_DIVIDE_BY_ZERO 'a'
%define ERROR_CODE_DEBUG 'b'
%define ERROR_CODE_NON_MASKABLE 'c'
%define ERROR_CODE_BREAKPOINT 'd'
%define ERROR_CODE_OVERFLOW 'e'
%define ERROR_CODE_RANGE_EXCEEDED 'f'
%define ERROR_CODE_INVALID_OPCODE 'g'
%define ERROR_CODE_DEVICE_NOT_AVAILABLE 'h'
%define ERROR_CODE_DOUBLE_FAULT 'i'
%define ERROR_CODE_COPROCESSOR_SEG_OV 'j'
%define ERROR_CODE_INVALID_TSS 'k'
%define ERROR_CODE_SEGMENT_NOT_PRESENT 'l'
%define ERROR_CODE_STACK_SEGMENT 'm'
%define ERROR_CODE_GENERAL_PROTECTION 'n'
%define ERROR_CODE_PAGE_FAULT 'o'
%define ERROR_CODE_X87_FLOATING_POINT 'p'
%define ERROR_CODE_ALIGNMENT_CHECK_IDT 'q'
%define ERROR_CODE_MACHINE_CHECK 'r'
%define ERROR_CODE_SIMD 's'
%define ERROR_CODE_VIRTUALIZATION 't'
%define ERROR_CODE_SECURITY 'u'
;********************************************************************************
; Datos inicializados
;********************************************************************************
SECTION .data
exceptionMessage db "e",NULL
pfPointer dd 0x00 ; Puntero a la tabla de directorio
pfPTP dd 0x00 ; Puntero a la tabla de pagina
pageNewTablePointer dd 0x00 ; Puntero a la nueva tabla de paginacion a crear
pageDestinationPointer dd 0x00 ; Puntero a la nueva dirección fisica a marcar
;********************************************************************************
; Codigo de las excepciones
;********************************************************************************
SECTION .main32 progbits
;********************************************************************************
; @fn exceptionLoadHandlers()
; @brief Carga la definicion de los handlers de las excepciones en la IDT
;********************************************************************************
exceptionLoadHandlers:
mov eax, divideByZeroErrorHandler
mov [IDT + 0x0 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x0 * 8 + 6], ax ;Parte alta
mov eax, debugHandler
mov [IDT + 0x1 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x1 * 8 + 6], ax ;Parte alta
mov eax, nonmaskableInterruptHandler
mov [IDT + 0x2 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x2 * 8 + 6], ax ;Parte alta
mov eax, breakpointHandler
mov [IDT + 0x3 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x3 * 8 + 6], ax ;Parte alta
mov eax, overflowHandler
mov [IDT + 0x4 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x4 * 8 + 6], ax ;Parte alta
mov eax, boundRangeExceededHandler
mov [IDT + 0x5 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x5 * 8 + 6], ax ;Parte alta
mov eax, invalidOpCodeHandler
mov [IDT + 0x6 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x6 * 8 + 6], ax ;Parte alta
mov eax, deviceNotAvailalbleHandler
mov [IDT + 0x7 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x7 * 8 + 6], ax ;Parte alta
mov eax, doubleFaultHandler
mov [IDT + 0x8 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x8 * 8 + 6], ax ;Parte alta
mov eax, coprocessorSegmentOverrunHandler
mov [IDT + 0x9 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x9 * 8 + 6], ax ;Parte alta
mov eax, invalidTSSHandler
mov [IDT + 0xA * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0xA * 8 + 6], ax ;Parte alta
mov eax, segmentNotPresentHandler
mov [IDT + 0xB * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0xB * 8 + 6], ax ;Parte alta
mov eax, stackSegmentFaultHandler
mov [IDT + 0xC * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0xC * 8 + 6], ax ;Parte alta
mov eax, generalProtectionFaultHandler
mov [IDT + 0xD * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0xD * 8 + 6], ax ;Parte alta
mov eax, pageFaultHandler
mov [IDT + 0xE * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0xE * 8 + 6], ax ;Parte alta
mov eax, x87FloatingPointExceptionHandler
mov [IDT + 0x10 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x10 * 8 + 6], ax ;Parte alta
mov eax, alignmentCheckIDTHandler
mov [IDT + 0x11 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x11 * 8 + 6], ax ;Parte alta
mov eax, machineCheckHandler
mov [IDT + 0x12 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x12 * 8 + 6], ax ;Parte alta
mov eax, simdFloatingPointExceptionHandler
mov [IDT + 0x13 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x13 * 8 + 6], ax ;Parte alta
mov eax, virtualizationExceptionHandler
mov [IDT + 0x14 * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x14 * 8 + 6], ax ;Parte alta
mov eax, securityExceptionHandler
mov [IDT + 0x1E * 8], ax ;Parte baja
shr eax, 16 ;Roto 16bit
mov [IDT+ 0x1E * 8 + 6], ax ;Parte alta
ret
;********************************************************************************
; @fn exceptionSetNewPagePointer(void *newPagePointer)
; @brief Setter de la direccion de memoria para la nueva tabla de paginacion
;********************************************************************************
exceptionSetNewPagePointer:
push ebp ; Guardo los registros
mov ebp, esp
push eax
push ebx
mov eax, [ebp + 8] ; Cargo el valor en eax
mov ebx, pageNewTablePointer ; Obtengo el valor del puntero a la nueva tabla de paginacion
mov [ebx], eax ; Cargo el valor que recibi
pop ebx
pop eax
pop ebp
ret
;********************************************************************************
; @fn exceptionSetNewDestinationPointer(void *newPagePointer)
; @brief Setter de la direccion de memoria para la nueva direccion paginada (fisica no lineal)
;********************************************************************************
exceptionSetNewDestinationPointer:
push ebp ; Guardo los registros
mov ebp, esp
push eax
push ebx
mov eax, [ebp + 8] ; Cargo el valor en eax
mov ebx, pageDestinationPointer ; Obtengo el valor del puntero a la nueva tabla de paginacion
mov [ebx], eax ; Cargo el valor que recibi
pop ebx
pop eax
pop ebp
ret
;********************************************************************************
; @fn divideByZeroErrorHandler
; @brief Handler de excepcion de division por cero
;********************************************************************************
divideByZeroErrorHandler:
xchg bx,bx
mov al, ERROR_CODE_DIVIDE_BY_ZERO
jmp undefinedHandlerException
;********************************************************************************
; @fn debugHandler
; @brief Handler de excepcion de debug
;********************************************************************************
debugHandler:
xchg bx,bx
mov al, ERROR_CODE_DEBUG
jmp undefinedHandlerException
;********************************************************************************
; @fn nonmaskableInterruptHandler
; @brief Handler de excepcion de interrupcion no enmascarable
;********************************************************************************
nonmaskableInterruptHandler:
xchg bx,bx ;Magix breakpoint
mov al, ERROR_CODE_NON_MASKABLE
jmp undefinedHandlerException
;********************************************************************************
; @fn breakpointHandler
; @brief Handler de excepcion de breakpoint
;********************************************************************************
breakpointHandler:
xchg bx,bx
mov al, ERROR_CODE_BREAKPOINT
jmp undefinedHandlerException
;********************************************************************************
; @fn overflowHandler
; @brief Handler de excepcion de overflow
;********************************************************************************
overflowHandler:
xchg bx,bx
mov al, ERROR_CODE_OVERFLOW
jmp undefinedHandlerException
;********************************************************************************
; @fn boundRangeExceededHandler
; @brief Handler de excepcion de bound range exceeded
;********************************************************************************
boundRangeExceededHandler:
xchg bx,bx
mov al, ERROR_CODE_RANGE_EXCEEDED
jmp undefinedHandlerException
;********************************************************************************
; @fn boundRangeExceededHandler
; @brief Handler de excepcion de opcode invalido
;********************************************************************************
invalidOpCodeHandler:
xchg bx,bx
mov al, ERROR_CODE_INVALID_OPCODE
jmp undefinedHandlerException
;********************************************************************************
; @fn deviceNotAvailalbleHandler
; @brief Handler de excepcion de dispositivo invalido
;********************************************************************************
deviceNotAvailalbleHandler:
xchg bx,bx
mov al, ERROR_CODE_DEVICE_NOT_AVAILABLE
jmp undefinedHandlerException
;********************************************************************************
; @fn doubleFaultHandler
; @brief Handler de excepcion de doble falta
;********************************************************************************
doubleFaultHandler:
xchg bx,bx
mov al, ERROR_CODE_DOUBLE_FAULT
jmp undefinedHandlerException
;********************************************************************************
; @fn coprocessorSegmentOverrunHandler
; @brief Handler de excepcion de overrun de segmento de coprocesador
;********************************************************************************
coprocessorSegmentOverrunHandler:
xchg bx,bx
mov al, ERROR_CODE_COPROCESSOR_SEG_OV
jmp undefinedHandlerException
;********************************************************************************
; @fn invalidTSSHandler
; @brief Handler de excepcion de TSS invalido
;********************************************************************************
invalidTSSHandler:
xchg bx,bx
mov al, ERROR_CODE_INVALID_TSS
jmp undefinedHandlerException
;********************************************************************************
; @fn segmentNotPresentHandler
; @brief Handler de excepcion de segmento no presente
;********************************************************************************
segmentNotPresentHandler:
xchg bx,bx
mov al, ERROR_CODE_SEGMENT_NOT_PRESENT
jmp undefinedHandlerException
;********************************************************************************
; @fn stackSegmentFaultHandler
; @brief Handler de excepcion de segmento de stack
;********************************************************************************
stackSegmentFaultHandler:
xchg bx,bx
mov al, ERROR_CODE_STACK_SEGMENT
jmp undefinedHandlerException
;********************************************************************************
; @fn generalProtectionFaultHandler
; @brief Handler de excepcion de proteccion general
;********************************************************************************
generalProtectionFaultHandler:
xchg bx,bx
mov al, ERROR_CODE_GENERAL_PROTECTION
jmp undefinedHandlerException
;********************************************************************************
; @fn pageFaultHandler
; @brief Handler de excepcion de fallo de pagina
;********************************************************************************
pageFaultHandler:
xchg bx, bx
push ebx
push eax
mov eax, [esp + 16] ; Obtengo el codigo de error
and eax, PTDP_ATTRIBUTE; Aplico una and para concer el estado de presencia de la dirección lineal que se desea acceder
jnz pageFaultPresent; Como la pagina esta presente el problema es otro
; Evaluo si la entrada de la PDPT esta presente
pageFaultTestPDPT:
mov eax, cr2 ; Paso a eax el valor de la direccion lineal que produjo el fallo de pagina
shr eax, PDPT_ROTATION_BITS; Roto 30 bits
and eax, PDPT_ENTRY_MASK ; Andeo para comparar y evaluar si hay una entrada presente en los punteros a tabla de directorio de paginas
mov ebx, PAE_ENTRY_SIZE; Paso a ebx el valor de 8
mul ebx ; Multiplico por el numero de bytes de las entradas de la PDPT
mov ebx, cr3 ; Traigo el valor de CR3 = PDPT a ebx
add eax, ebx ; Incremento el puntero eax a ebx
mov [pfPointer], eax; Cargo el puntero
mov ebx, [eax] ; Cargo el contenido de esa entrada y evaluo si está presente
and ebx, PTDP_ATTRIBUTE; Andeo
jz pageFaultDirectoryAbscent
;Tengo que evaluar si la entrada de tabla de pagina existe o no
pageFaultTestDPT:
mov eax, cr2 ; Paso nuevamente la dirección lineal a eax
shr eax, DPT_ROTATION_BITS; Roto
and eax, TABLE_OFFSET_MASK ; Aplico la mascara para quedarme con la dirección lineal correcta
mov ebx, PAE_ENTRY_SIZE
mul ebx ; Multiplico por 8
mov ebx, [pfPointer]; Paso ebx la dirección que esta en la tabla de punteros de tablas de directorios
mov ebx, [ebx]
and ebx, TABLE_ENTRY_MASK; Aplico mascara para manter la direccion y olvidarme de los atributos
add eax, ebx ; Puntero en eax a la tabla de directorios para evaluar la tabla de paginas si esta presente y con permisos
mov [pfPointer], eax; Guardo el puntero al directorio de paginas
mov ebx, [eax] ; Aca tengo en ebx el puntero a la tabla de paginas si es que existe
and ebx, PTDP_ATTRIBUTE; Aplico la and para chequear que la tabla de paginas este presente
jz pageFaultPageTableAbscent
;Tengo que evaluar si hay entrada de pagina
pageFaultTestPT:
mov eax, cr2 ; Paso nuevamente la direccion lineal
shr eax, PT_ROTATION_BITS; Roto
and eax, TABLE_OFFSET_MASK; Aplico mascara
mov ebx, PAE_ENTRY_SIZE; Cargo el tamaño de entrada
mul ebx ; Multiplico
mov ebx, [pfPointer]; Obtengo el puntero a la entrada de la tabla de paginas
mov ebx, [ebx]
and ebx, TABLE_ENTRY_MASK; Aplico la mascara por los atributos
add eax, ebx ; Sumo el offset
mov ebx, [pageDestinationPointer]; Obtengo la nueva direccion
or ebx, ENTRY_ATTRIBUTE; Aplico los atributos
mov [eax], ebx ; Cargo la direccion de la nueva pagina
mov ebx, [pageDestinationPointer]; Obtengo la vieja direccion
add ebx, PAGE_SIZE ; Sumo el tamaño de pagina
mov [pageDestinationPointer], ebx
jmp pageFaultEnd ; Termino
pageFaultDirectoryAbscent:
; Faltaba la entrada de directorio y en eax tengo la dirección del offset donde cargar la nueva entrada
; Debo crear: tabla de directorio, tabla de pagina y entrada de la pagina.
; En eax tengo la direccion de memoria a donde debiera dejar la dirección de la tabla de directorio
mov ebx, [pageNewTablePointer] ; Paso a ebx el puntero a la tabla de directorios
or ebx, PTDP_ATTRIBUTE; Aplico una or a ebx para colocar los atributos
mov [eax], ebx ; Cargo el puntero en ebx a la tabla de atributos
mov eax, [pageNewTablePointer] ; Obtengo el anterior puntero, le sumo el tamaño de una pagina y lo vuelvo a cargar en el puntero
mov [pfPointer], eax
add eax, PAGE_SIZE
mov [pageNewTablePointer], eax
mov eax, cr2 ; Obtengo la dirección lineal que genero
shr eax, DPT_ROTATION_BITS; Roto la dirección 12 bits para quedarme con el offset de la dirección
and eax, TABLE_OFFSET_MASK; Andeo para quedarme con los bits
mov ebx, PAE_ENTRY_SIZE
mul ebx ; Multiplico por 8 y ya tengo el offset en eax de la entrada de pagina
mov ebx, [pfPointer]; Obtengo el puntero y me voy a mover el offset
add eax, ebx ; Tengo entonces en eax la dirección en donde debo cargar el puntero a la entrada de página
pageFaultPageTableAbscent:
; Tengo entrada en la PDPT para la tabla de directorio pero en la tabla de directorio no tengo una entrada
; a una tabla de directorio valida. Entonces simplemente lo que hacemos es crear una tabla con una entrada valida
; En eax tengo la direccion de memoria a donde debiera dejar la dirección de la tabla de paginas
mov ebx, [pageNewTablePointer] ; Paso a ebx el puntero a la tabla de paginas
or ebx, ENTRY_ATTRIBUTE; Aplico una or a ebx para colocar los atributos
mov [eax], ebx ; Cargo el puntero en ebx a la tabla de pagianas
mov eax, [pageNewTablePointer] ; Obtengo el anterior puntero, le sumo el tamaño de una pagina y lo vuelvo a cargar en el puntero
mov [pfPointer], eax
add eax, PAGE_SIZE
mov [pageNewTablePointer], eax
pageFaultPageTableWrite:
mov eax, cr2 ; Obtengo la dirección lineal que genero
shr eax, PT_ROTATION_BITS; Roto la dirección 12 bits para quedarme con el offset de la dirección
and eax, TABLE_OFFSET_MASK; Andeo para quedarme con los bits
mov ebx, PAE_ENTRY_SIZE
mul ebx ; Multiplico por 8 y ya tengo el offset en eax de la entrada de pagina
mov ebx, [pfPointer]; Obtengo el puntero y me voy a mover el offset
add eax, ebx ; Tengo entonces en eax la dirección en donde debo cargar el puntero a la entrada de página
mov ebx, [pageDestinationPointer]
or ebx, ENTRY_ATTRIBUTE
mov [eax], ebx ; Cargo ya con los atributos la nueva direccion de la pagina
mov ebx, [pageDestinationPointer]
add ebx, PAGE_SIZE
mov [pageDestinationPointer], ebx
jmp pageFaultEnd
pageFaultEnd:
mov eax, cr3
mov cr3, eax
pop eax ; Restauro edx
pop ebx ; Restauro ebx
add esp, 4 ; Restauro la pila por el error code pusheado
xchg bx, bx
iret
pageFaultPresent:
nop
jmp $-1
;********************************************************************************
; @fn x87FloatingPointExceptionHandler
; @brief Handler de excepcion de unidad de punto flotante
;********************************************************************************
x87FloatingPointExceptionHandler:
xchg bx,bx
mov al, ERROR_CODE_X87_FLOATING_POINT
jmp undefinedHandlerException
;********************************************************************************
; @fn alignmentCheckIDTHandler
; @brief Handler de excepcion de check de alineacion de IDT
;********************************************************************************
alignmentCheckIDTHandler:
xchg bx,bx
mov al, ERROR_CODE_ALIGNMENT_CHECK_IDT
jmp undefinedHandlerException
;********************************************************************************
; @fn machineCheckHandler
; @brief Handler de excepcion de check de maquina
;********************************************************************************
machineCheckHandler:
xchg bx,bx
mov al, ERROR_CODE_MACHINE_CHECK
jmp undefinedHandlerException
;********************************************************************************
; @fn simdFloatingPointExceptionHandler
; @brief Handler de excepcion de SIMD
;********************************************************************************
simdFloatingPointExceptionHandler:
xchg bx,bx
mov al, ERROR_CODE_SIMD
jmp undefinedHandlerException
;********************************************************************************
; @fn virtualizationExceptionHandler
; @brief Handler de excepcion de virtualizacion
;********************************************************************************
virtualizationExceptionHandler:
xchg bx,bx
mov al, ERROR_CODE_VIRTUALIZATION
jmp undefinedHandlerException
;********************************************************************************
; @fn securityExceptionHandler
; @brief Handler de excepcion de seguridad
;********************************************************************************
securityExceptionHandler:
xchg bx,bx
mov al, ERROR_CODE_SECURITY
jmp undefinedHandlerException
;********************************************************************************
; @fn undefinedHandlerException
; @brief El código llega a este punto cuando no tiene un handler definido
; para la excepcion pero la interrupcion se produce
;********************************************************************************
undefinedHandlerException:
xchg bx,bx ;Magix breakpoint
call videoClearScreen
push VIDEO_WORD_FOREGROUND_RED_MASK | VIDEO_WORD_INTENSITY_MASK
push 0
push 0
mov [exceptionMessage], al
push exceptionMessage
call videoPrint
add esp, 16
hlt
jmp $-1
iret