diff --git a/readme.md b/readme.md index 6eb33ac..96ef283 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,4 @@ # Custom BIOS / ROM Project -## Projet BIOS / ROM personnalisé --- diff --git a/src/bda.asm b/src/bda.asm index bd6a704..9f586bf 100644 --- a/src/bda.asm +++ b/src/bda.asm @@ -32,12 +32,6 @@ %define BDA_INFO_MEM_SIZE 0x0014 ; Memory size in Kbytes %define BDA_INFO_MEM_SEG BDA_INFO_MEM_SIZE+2 ; highest Memory Segment - -%define BDA_MOUSE_BUFFER 0x0068 ; dword -%define BDA_MOUSE_IDX BDA_MOUSE_BUFFER+4 ; byte -%define BDA_MOUSE_X BDA_MOUSE_BUFFER+5 ; word -%define BDA_MOUSE_Y BDA_MOUSE_BUFFER+7 ; word - ; video related information (compatible with VGA bios) %define BDA_VIDEO_CURR_MODE 0x0049 %define BDA_VIDEO_COLUMNS 0x004A @@ -51,4 +45,19 @@ ; 40:62 byte Active display page number ; 40:63 word Base port address for active 6845 CRT controller 3B4h = mono, 3D4h = color ; 40:65 byte 6845 CRT mode control register value (port 3x8h) ; EGA/VGA values emulate those of the MDA/CGA -; 40:66 byte CGA current color palette mask setting (port 3d9h) ; EGA and VGA values emulate the CGA \ No newline at end of file +; 40:66 byte CGA current color palette mask setting (port 3d9h) ; EGA and VGA values emulate the CGA + + +; +; information relative à la souris +; + +%define BDA_MOUSE_SEG 0x0050 + +%define BDA_MOUSE_BUFFER 0x0000 ; dword; buffer (jusqu'à 4 octets) +%define BDA_MOUSE_IDX 0x0004 ; byte 0..3 +%define DBA_MOUSE_PACKETLEN 0x0005 +; 0x0006 +%define BDA_MOUSE_STATUS 0x0007 ; byte +%define BDA_MOUSE_X 0x0008 ; word +%define BDA_MOUSE_Y 0x000A ; word \ No newline at end of file diff --git a/src/boot.asm b/src/boot.asm index 9ec7168..da5ec0b 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -50,6 +50,7 @@ org 0 %include ".\drivers\debug.asm" %include ".\drivers\gfx_cgam.asm" %include ".\drivers\mouse_ps2.asm" +%include ".\services\generic.asm" err_vganok db 'VGA Not Initialized',0 err_end db 'code completed successfully',0 @@ -81,6 +82,16 @@ reset: call gfx_init + mov cx,50 +.bcl: ; mov dx,cx + mov bl,0 + push cx + call gfx_putpixel + pop cx + inc cx + cmp cx,150 + jle .bcl + call mouse_init mov ax,cs @@ -89,168 +100,8 @@ reset: mov si, err_end call debug_puts -endless: nop +endless: hlt jmp endless - -; --------------------------------------------------------------------------- -; Test si le vecteur INT 10h à été modifié (par la ROM) -; -; Si le vecteur n'a pas été modifiée, on considère que la ROM video n'a pas -; été chargée. -; --------------------------------------------------------------------------- -setup_check_vga: - ; vérification de l'offset 0x0000:0x0040 qui DOIT etre différent de @default_isr - xor ax,ax - mov es,ax - ; Lire INT10: offset+segment depuis 0000:0040 - mov bx, [es:0x0040] ; BX = offset INT10 - mov cx, [es:0x0042] ; CX = segment INT10 - mov ax, cs - - ; Comparer avec default_isr (offset) et CS (segment) - mov dx, default_isr ; DX = offset default_isr (dans notre CS) - cmp bx, dx - jne .init_ok ; vecteur different, bios initialisé - cmp cx, ax - jne .init_ok - - mov ax,cs ; vecteur identique, sans doute pas d'initialisation - mov ds,ax - - mov si, err_vganok - call debug_puts -.init_ok: - ret - -; --------------------------------------------------------------------------- -; Détection les ROM supplementaires -; Teste la RAM de 0xC000 jusqu’à 0xE000, par pas de 2KB. -; -; Si une ROM est détectée, le code de la ROM sera appelé. -; --------------------------------------------------------------------------- -setup_load_rom: - mov bx, 0xC000 -.scanloop: - mov ds, bx - cmp word[0x0000],0xAA55 ; ROM signature - jne .norom - - ; Debug - mov al,'.' - call debug_putc - - ; appel le code (en 0x0003) de la ROM - push cs - push word .norom ; address de retour - - push ds - push 0x0003 - retf ; call far ds:0x0003 -.norom: - add bx, 0x80 ; add 2kb - cmp bx, 0xE000 - jbe .scanloop -.end: - ret - -; --------------------------------------------------------------------------- -; Détection RAM conventionnelle -; Teste la RAM de MEM_SEG_DEB jusqu’à 0xA000 (640KB), par pas de 1KB. -; Méthode: sauvegarde 1 mot, écrit 2 patterns, relit, restaure. -; -; Résultats: -; AX = taille détectée en Ko (KB) à partir de 0 jusqu’au “top conventionnel” -; DX = top_segment (segment du premier Ko NON valide) (optionnel) -; -; Précautions: -; - Ne testez PAS une zone où se trouve votre pile / variables. -; - Si votre pile est à 0000:7C00 (phys 0x7C00), commencez au moins à 0x0800. -; - Ne testez pas au-delà de 0xA000 (début VGA/vidéo). -; --------------------------------------------------------------------------- -setup_ram: - xor ax, ax ; AX = compteur KB trouvés - mov dx, MEM_SEG_DEB ; DX = segment courant testé - mov cx, MEM_SEG_END ; CX = segment fin (exclu) - xor di, di ; tester au début du bloc 1KB: ES:0000 - -.loop_seg: - cmp dx, cx - jae .done - mov es, dx - - ; sauvegarder le mot existant - mov bx, [es:di] - - ; pattern 1 - mov word [es:di], 0x55AA - cmp word [es:di], 0x55AA - jne .fail_restore - - ; pattern 2 (inverse) - mov word [es:di], 0xAA55 - cmp word [es:di], 0xAA55 - jne .fail_restore - - ; restaurer - mov [es:di], bx - - ; OK: avancer d’1KB - inc ax ; +1KB valide - add dx, MEM_SEG_STEP - jmp .loop_seg - -.fail_restore: - ; restaurer avant de sortir - mov [es:di], bx - -.done: - ; AX contient le nb de KB valides *à partir de MEM_SEG_DEB*. - ; Si vous voulez une taille “depuis 0KB”, ajoutez MEM_SEG_DEB*16/1024 = MEM_SEG_DEB/64. - ; - ; base_kb = MEM_SEG_DEB / 0x0040 (car 1KB = 0x40 segments) - mov bx, MEM_SEG_DEB - shr bx, 6 ; /64 = /0x40 => KB de base - add ax, bx ; AX = taille conventionnelle totale en KB (approx. 0..640) - ; DX = segment du premier bloc NON valide (top) - ; DX est déjà positionné (segment courant) - - ; stocker l'information dans le BDA - mov bx, BDA_SEGMENT - mov ds, bx - mov [BDA_INFO_MEM_SIZE], ax - mov [BDA_INFO_MEM_SEG],dx - - ret - - -; --------------------------------------------------------------------------- -; IVT install (8088, mode réel) - remplit les 256 vecteurs avec un handler IRET -; --------------------------------------------------------------------------- -setup_ivt: - ; installation de la table d'interrupts - xor ax, ax - mov es, ax ; ES = 0000h -> base IVT - xor di, di ; DI = 0000h -> offset IVT - - mov ax, default_isr ; offset du handler - mov dx, cs ; segment du handler (ROM) - - mov cx, 256 ; 256 vecteurs -.fill: - stosw ; write offset (AX) -> [ES:DI], DI += 2 - xchg ax, dx ; AX = segment, DX = offset - stosw ; write segment (AX) -> [ES:DI], DI += 2 - xchg ax, dx ; AX = offset, DX = segment - loop .fill - ; fin de la table d'interrupt - ret - -; --------------------------------------------------------------------------- -; Handler par défaut: fait juste IRET -; IMPORTANT: doit être FAR (appelé par le CPU via IVT), et terminer par IRET -; --------------------------------------------------------------------------- -default_isr: - iret ; ------------------------------------------------------------------ ; Padding jusqu'au reset vector @@ -262,5 +113,6 @@ times 0xFFF0 - ($ - $$) db 0xFF ; ------------------------------------------------------------------ reset_vector: jmp far 0xF000:reset +; filling builddate db '06/01/2026',0 diff --git a/src/drivers/gfx_cgam.asm b/src/drivers/gfx_cgam.asm index 279243d..bdb6b05 100644 --- a/src/drivers/gfx_cgam.asm +++ b/src/drivers/gfx_cgam.asm @@ -34,7 +34,6 @@ %define CGA_ODD_BANK 0x2000 %define BG16_SIZE 48 - ; ------------------------------------------------------------ ; initialise le mode graphique (via l'int 10h) ; @@ -42,7 +41,7 @@ ; ------------------------------------------------------------ gfx_init: ; init graphics mode - mov ah, 0x00 ; AH=00h set video mode + mov ah, 0x00 ; AH=00h set video mode mov al, GFX_MODE int 0x10 @@ -56,46 +55,47 @@ gfx_init: ; In: ; CX = x (0..639) ; DX = y (0..199) -; AL = color (0=black, !=0=white) +; BL = color (0=black, !=0=white) ; ; ------------------------------------------------------------ gfx_putpixel: - push bx + push ax push di push es + + mov ax, VIDEO_SEG + mov es,ax - mov ax, VIDEO_SEG - mov es, ax + ; calcul de l'offset 'y': + ; si y est impaire, DI+=0x2000 + + ; DI = (y>>1)*80 + (x>>3) + (y&1)*0x2000 + mov ax, dx + shr ax, 1 ; ax = y/2 - ; DI = (y>>1)*80 + (x>>3) + (y&1)*0x2000 - mov bx, dx - and bx, 1 ; BX = y&1 + mov di, ax ; di = y/2 + shl di, 4 ; di = (y/2)*16 - mov ax, dx - shr ax, 1 ; AX = y>>1 - mov di, ax - mov ax, di - mov di, CGA_STRIDE - mul di ; DX:AX = (y>>1)*80 - mov di, ax - - test bx, 1 - jz .bank_ok + shl ax, 6 ; ax = (y/2)*64 + add di, ax ; di = (y/2)*(16+64) = *80 + + mov ax, cx ; x + shr ax, 3 ; AX = x/8 + add di, ax + + ; ligne paire/impaire + test dl, 1 + jz .ligne_paire add di, CGA_ODD_BANK -.bank_ok: - mov ax, cx - shr ax, 3 ; AX = x>>3 - add di, ax +.ligne_paire: ; masque bit = 0x80 >> (x&7) - mov bl, cl - and bl, 7 ; BL = x&7 + and cl, 7 ; cl = x&7 mov ah, 080h - mov cl, bl - shr ah, cl ; AH = bitmask + shr ah, cl ; AH = bitmask ; write - cmp al, 0 + cmp bl, 0 je .clear .set: @@ -109,7 +109,7 @@ gfx_putpixel: .done: pop es pop di - pop bx + pop ax ret ; ------------------------------------------------------------ diff --git a/src/drivers/mouse_ps2.asm b/src/drivers/mouse_ps2.asm index b13a574..3666c29 100644 --- a/src/drivers/mouse_ps2.asm +++ b/src/drivers/mouse_ps2.asm @@ -25,14 +25,24 @@ ; ; controleur de souris via le i8042 (PC Classique) ; +%define BDA_SEGMENT 0x0040 -%define PS2_PORT_BUFFER 0x60 -%define PS2_PORT_CTRL 0x64 +%define PS2_PORT_BUFFER 0x60 +%define PS2_PORT_CTRL 0x64 -%define MOUSE_CMD_RESET 0xff -%define MOUSE_CMD_DEFAULT 0xf6 -%define MOUSE_EN_STREAM 0xf4 -%define MOUSE_DIS_STREAM 0xf5 +%define MOUSE_CMD_RESET 0xFF +%define MOUSE_CMD_DEFAULT 0xF6 +%define MOUSE_EN_STREAM 0xF4 +%define MOUSE_DIS_STREAM 0xF5 +%define MOUSE_GET_ID 0xF2 +%define MOUSE_SET_RATE 0xF3 + +%define MOUSE_ACK 0xFA + +%define I8042_CMD_EN_AUX 0xA8 +%define I8042_CMD_RD_CBYTE 0x20 +%define I8042_CMD_WR_CBYTE 0x60 +%define I8042_CMD_WRITE_AUX 0xD4 mouse_arrow: dw 1001111111111111b ; 0x9FFF @@ -68,6 +78,10 @@ mouse_arrow: dw 0000000110000000b ; 0x0180 dw 0000000000000000b ; 0x0000 +; ------------------------------------------------------------ +; initialise le i8042 keyboard and mouse (PS/2) +; +; ------------------------------------------------------------ mouse_init: ; Activer le port souris mov ax, BDA_SEGMENT @@ -76,43 +90,169 @@ mouse_init: ; effacer les variables du drivers mov [BDA_MOUSE_IDX],0 mov dword [BDA_MOUSE_BUFFER],0 + mov byte [DBA_MOUSE_PACKETLEN],3 - mov al, 0xA8 - out PS2_PORT_CTRL, al - - ; Lire le command byte - mov al, 0x20 - out PS2_PORT_CTRL, al - in al, PS2_PORT_BUFFER + call ps2_flush_output + ; Activer le port souris (AUX) + call ps2_wait_ready_write + mov al, I8042_CMD_EN_AUX + out PS2_PORT_CTRL, al + + ; Lire command byte + call ps2_wait_ready_write + mov al, I8042_CMD_RD_CBYTE + out PS2_PORT_CTRL, al + call ps2_read ; AL = command byte + ; Activer IRQ12 (bit 1) - or al, 0x02 + or al, 02h + mov ah, al - ; Réécrire le command byte - mov ah, al - mov al, PS2_PORT_BUFFER - out PS2_PORT_CTRL, al - mov al, ah - out PS2_PORT_BUFFER, al + ; Réécrire command byte (commande 0x60 envoyée à 0x64) + call ps2_wait_ready_write + mov al, I8042_CMD_WR_CBYTE + out PS2_PORT_CTRL, al + call ps2_wait_ready_write + mov al, ah + out PS2_PORT_BUFFER, al + + call ps2_flush_output + + ; --- RESET souris: FA, AA, ID + mov bl, MOUSE_CMD_RESET + call mouse_sendcmd + call ps2_read ; 0xAA attendu (self-test OK) + call ps2_read ; ID (souvent 0x00) + + ; Defaults: FA + mov bl, MOUSE_CMD_DEFAULT + call mouse_sendcmd + + ; Enable streaming: FA + mov bl, MOUSE_EN_STREAM + call mouse_sendcmd + + ; (option) détecter 3/4 bytes via F3 200/100/80 + F2 + ; call mouse_detect_packet_len + + ; installer ISR IRQ12 (INT 74h) + ; call mouse_install_isr + + + + ; installer le handler ret + +mouse_detect_packet_len: + mov byte [DBA_MOUSE_PACKETLEN], 3 -; envoyer une commande souris -mouse_sendcmd: + ; F3 200 + mov bl, MOUSE_SET_RATE + call mouse_sendcmd + mov bl, 200 + call mouse_sendcmd + + ; F3 100 + mov bl, MOUSE_SET_RATE + call mouse_sendcmd + mov bl, 100 + call mouse_sendcmd + + ; F3 80 + mov bl, MOUSE_SET_RATE + call mouse_sendcmd + mov bl, 80 + call mouse_sendcmd + + ; F2 -> ID + mov bl, MOUSE_GET_ID + call mouse_sendcmd + call ps2_read ; AL = ID + + cmp al, 03h + je .is4 + cmp al, 04h + je .is4 + ret +.is4: + mov byte [DBA_MOUSE_PACKETLEN], 4 + ret + +; ------------------------------------------------------------ +; fonction de gestion du i8042 +; +; ------------------------------------------------------------ + +; attendre que le 8042 soit pret a recevoir de l'information +ps2_wait_ready_write: .wait: - in al, PS2_PORT_CTRL - test al, 2 - jnz .wait - mov al, 0xD4 - out PS2_PORT_CTRL, al + in al, PS2_PORT_CTRL + test al, 02h ; IBF + jnz .wait + ret -.wait2: - in al, PS2_PORT_CTRL - test al, 2 - jnz .wait2 - mov al, bl ; BL = commande souris - out PS2_PORT_BUFFER, al +; attendre que le 8042 soit pret a lire de l'information +ps2_wait_ready_read: +.wait: + in al, PS2_PORT_CTRL + test al, 01h ; OBF + jz .wait + ret + +; lire de l'information depuis le 8042 +ps2_read: + call ps2_wait_ready_read + in al, PS2_PORT_BUFFER + ret + +; vide le buffer interne du 8042 (information(s) ignorée(s)) +ps2_flush_output: +.flush: + in al, PS2_PORT_CTRL + test al, 01h + jz .done + in al, PS2_PORT_BUFFER + jmp .flush +.done: ret + + +; ------------------------------------------------------------ +; envoye une commande souris +; +; BL = commande souris (ou data après une commande F3) +; +; renvoi CF=0 si ACK, CF=1 sinon +; ------------------------------------------------------------ +mouse_sendcmd: + call ps2_wait_ready_write + + mov al, I8042_CMD_WRITE_AUX + out PS2_PORT_CTRL, al + + call ps2_wait_ready_write + mov al, bl + out PS2_PORT_BUFFER, al + + call ps2_wait_ready_read ; AL = réponse + cmp al, MOUSE_ACK + jne .bad + clc + ret +.bad: + stc + ret + +; ------------------------------------------------------------ +; interrupt handler +; +; buffer[0] = status +; buffer[1] = déplacement x +; buffer[2] = déplacement y (inversé) +; +; ------------------------------------------------------------ mouse_handler: push ax push bx diff --git a/src/services/generic.asm b/src/services/generic.asm new file mode 100644 index 0000000..50ee15a --- /dev/null +++ b/src/services/generic.asm @@ -0,0 +1,208 @@ +; ============================================================================= +; Project : Custom BIOS / ROM +; File : generic.asm +; Author : frater +; Created : 06 jan 2026 +; +; License : GNU General Public License v3.0 or later (GPL-3.0+) +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . +; +; ============================================================================= + +; --------------------------------------------------------------------------- +; Détection RAM conventionnelle +; Teste la RAM de MEM_SEG_DEB jusqu’à 0xA000 (640KB), par pas de 1KB. +; Méthode: sauvegarde 1 mot, écrit 2 patterns, relit, restaure. +; +; Résultats: +; AX = taille détectée en Ko (KB) à partir de 0 jusqu’au “top conventionnel” +; DX = top_segment (segment du premier Ko NON valide) (optionnel) +; +; Précautions: +; - Ne testez PAS une zone où se trouve votre pile / variables. +; - Si votre pile est à 0000:7C00 (phys 0x7C00), commencez au moins à 0x0800. +; - Ne testez pas au-delà de 0xA000 (début VGA/vidéo). +; --------------------------------------------------------------------------- +setup_ram: + xor ax, ax ; AX = compteur KB trouvés + mov dx, MEM_SEG_DEB ; DX = segment courant testé + mov cx, MEM_SEG_END ; CX = segment fin (exclu) + xor di, di ; tester au début du bloc 1KB: ES:0000 + +.loop_seg: + cmp dx, cx + jae .done + mov es, dx + + ; sauvegarder le mot existant + mov bx, [es:di] + + ; pattern 1 + mov word [es:di], 0x55AA + cmp word [es:di], 0x55AA + jne .fail_restore + + ; pattern 2 (inverse) + mov word [es:di], 0xAA55 + cmp word [es:di], 0xAA55 + jne .fail_restore + + ; restaurer + mov [es:di], bx + + ; OK: avancer d’1KB + inc ax ; +1KB valide + add dx, MEM_SEG_STEP + jmp .loop_seg + +.fail_restore: + ; restaurer avant de sortir + mov [es:di], bx + +.done: + ; AX contient le nb de KB valides *à partir de MEM_SEG_DEB*. + ; Si vous voulez une taille “depuis 0KB”, ajoutez MEM_SEG_DEB*16/1024 = MEM_SEG_DEB/64. + ; + ; base_kb = MEM_SEG_DEB / 0x0040 (car 1KB = 0x40 segments) + mov bx, MEM_SEG_DEB + shr bx, 6 ; /64 = /0x40 => KB de base + add ax, bx ; AX = taille conventionnelle totale en KB (approx. 0..640) + ; DX = segment du premier bloc NON valide (top) + ; DX est déjà positionné (segment courant) + + ; stocker l'information dans le BDA + mov bx, BDA_SEGMENT + mov ds, bx + mov [BDA_INFO_MEM_SIZE], ax + mov [BDA_INFO_MEM_SEG],dx + + ret + +; --------------------------------------------------------------------------- +; Détection les ROM supplementaires +; Teste la RAM de 0xC000 jusqu’à 0xE000, par pas de 2KB. +; +; Si une ROM est détectée, le code de la ROM sera appelé. +; --------------------------------------------------------------------------- +setup_load_rom: + mov bx, 0xC000 +.scanloop: + mov ds, bx + cmp word[0x0000],0xAA55 ; ROM signature + jne .norom + + ; Debug + mov al,'.' + call debug_putc + + ; appel le code (en 0x0003) de la ROM + push cs + push word .norom ; address de retour + + push ds + push 0x0003 + retf ; call far ds:0x0003 +.norom: + add bx, 0x80 ; add 2kb + cmp bx, 0xE000 + jbe .scanloop +.end: + ret + +; --------------------------------------------------------------------------- +; Test si le vecteur INT 10h à été modifié (par la ROM) +; +; Si le vecteur n'a pas été modifiée, on considère que la ROM video n'a pas +; été chargée. +; --------------------------------------------------------------------------- +setup_check_vga: + ; vérification de l'offset 0x0000:0x0040 qui DOIT etre différent de @default_isr + xor ax,ax + mov es,ax + ; Lire INT10: offset+segment depuis 0000:0040 + mov bx, [es:0x0040] ; BX = offset INT10 + mov cx, [es:0x0042] ; CX = segment INT10 + mov ax, cs + + ; Comparer avec default_isr (offset) et CS (segment) + mov dx, default_isr ; DX = offset default_isr (dans notre CS) + cmp bx, dx + jne .init_ok ; vecteur different, bios initialisé + cmp cx, ax + jne .init_ok + + mov ax,cs ; vecteur identique, sans doute pas d'initialisation + mov ds,ax + + mov si, err_vganok + call debug_puts +.init_ok: + ret + + +; --------------------------------------------------------------------------- +; IVT install (8088, mode réel) - remplit les 256 vecteurs avec un handler IRET +; --------------------------------------------------------------------------- +setup_ivt: + ; installation de la table d'interrupts + xor ax, ax + mov es, ax ; ES = 0000h -> base IVT + xor di, di ; DI = 0000h -> offset IVT + + mov ax, default_isr ; offset du handler + mov dx, cs ; segment du handler (ROM) + + mov cx, 256 ; 256 vecteurs +.fill: + stosw ; write offset (AX) -> [ES:DI], DI += 2 + xchg ax, dx ; AX = segment, DX = offset + stosw ; write segment (AX) -> [ES:DI], DI += 2 + xchg ax, dx ; AX = offset, DX = segment + loop .fill + ; fin de la table d'interrupt + ret + +; --------------------------------------------------------------------------- +; IVT install (8088, mode réel) - installe un handler a une interrupt calculée +; +; ax = int ide +; dx = segment handler +; bx = offset handler +; --------------------------------------------------------------------------- +setup_setvector: + push es + push di + + shl ax,2 ; ax=id *4 + mov di,ax + + xor ax,ax + mov es, ax ; ES = 0000h -> base IVT + + mov ax, bx ; offset du handler + stosw ; write offset (AX) -> [ES:DI], DI += 2 + xchg ax, dx ; AX = segment, DX = offset + stosw ; write segment (AX) -> [ES:DI], DI += 2 + + pop di + pop es + ret + +; --------------------------------------------------------------------------- +; Handler par défaut: fait juste IRET +; IMPORTANT: doit être FAR (appelé par le CPU via IVT), et terminer par IRET +; --------------------------------------------------------------------------- +default_isr: + iret \ No newline at end of file