section .text ; ; Set up segment registers ; mov sp, STACK_SEGMENT mov ss, sp mov sp, STACK_SIZE push cs pop ds push word SCREEN_SEGMENT pop es ; Blank screen call clearScreen ; Say hello push word welcomeMessage push word welcomeMessage_size call printString add sp, 4 call newline ; Install keyboard handler push ds push word 0 pop ds cli mov [4 * KEYBOARD_INTERRUPT], word keyboardHandler mov [4 * KEYBOARD_INTERRUPT + 2], cs sti pop ds ; Ask for login push word loginMsg push word loginMsg_size call printString add sp, 4 ; Read login push word login push word login_size call readLine add sp, 4 ; Print login push word login push ax call printString add sp, 4 call newline ; Hang jmp $ ;;;;;;;;;;;;; ; Functions ; ;;;;;;;;;;;;; clearScreen: ; Clear screen and reset cursor position ; In: none ; Out: none ; Global: ; color The color to use ; es The screen segment ; cursor_pos Cursor position (modified) mov ah, [cs:color] mov al, 0 mov cx, SCREEN_COLS * SCREEN_ROWS xor di, di rep stosw mov [cs:cursor_pos], word 0 ret readChar: ; Read character ; In: none ; Out: ASCII code in AL ; Global: ; firstInput (modified) mov bl, [cs:firstInput] .loop0: cmp bl, [cs:lastInput] jne .end hlt jmp .loop0 .end: xor bh, bh mov al, [cs:inputBuffer + bx] inc bl and bl, 15 mov [cs:firstInput], bl ret readLine: ; Read line ; In: ; buffer address (word) ; buffer size (word) ; Out: ; string length (ax) push bp mov bp, sp mov di, [bp + 6] push es push ds pop es mov cx, [bp + 4] .loop0: call readChar cmp al, 13 je .end stosb loop .loop0 .end: pop es sub di, [bp + 6] mov ax, di pop bp ret printChar: ; In: ; character (byte) ; Out: none ; Global: ; color The color to use ; es The screen segment ; cursor_pos The cursor position (modified) push bp mov bp, sp mov al, [bp + 4] mov ah, [cs:color] mov di, [cs:cursor_pos] stosw mov [cs:cursor_pos], di pop bp ret printString: ; Print string ; In: ; String offset (word) ; String length (word) ; Out: ; none ; Global: ; color The color to use ; es The screen segment ; cursor_pos The cursor position (modified) push bp mov bp, sp mov si, [bp + 6] mov cx, [bp + 4] mov ah, [cs:color] mov di, [cs:cursor_pos] .loop0: lodsb ; load byte from string stosw ; store byte and color on screen loop .loop0 mov [cs:cursor_pos], di pop bp ret newline: ; Advance cursor to beginning of next line ; In: none ; Out: none ; Global: ; cursor_pos Cursor position (modified) ; Divide the cursor position by the number of bytes per row, ; add 1, then multiply by bytes per row mov ax, [cs:cursor_pos] xor dx, dx mov cx, SCREEN_COLS * 2 div cx inc ax mul cx mov [cs:cursor_pos], ax ret ;;;;;;;;;;;;;;;;;;;;;; ; Interrupt Handlers ; ;;;;;;;;;;;;;;;;;;;;;; keyboardHandler: ; save our registers! pusha ; Read code in al, 60h ; Ignore codes with high bit set test al, 80h jnz .end ; Read the ASCII code from the table mov bl, al xor bh, bh mov al, [cs:bx + keymap] ; Ignore keys with no ASCII code cmp al, 0 je .end ; Buffer character mov bl, [cs:lastInput] inc bl and bl, 15 cmp bl, [cs:firstInput] je .end ; buffer full, discard character xor bh, bh mov [cs:inputBuffer + bx - 1], al mov [cs:lastInput], bl .end: ; Send EOI mov al, 61h out 20h, al ; return popa iret ;;;;;;;; ; Data ; ;;;;;;;; section .data welcomeMessage db "Simple Kernel" welcomeMessage_size EQU $ - welcomeMessage loginMsg db "Login: " loginMsg_size EQU $ - loginMsg color db 7 ; White on black cursor_pos dw 0 keymap %include "keymap.inc" firstInput db 0 lastInput db 0 ;;;;;;;;;;;;;;;;;;;;;; ; Uninitialized data ; ;;;;;;;;;;;;;;;;;;;;;; section .bss inputBuffer resb 16 login resb 16 login_size EQU $ - login ;;;;;;;;;;;;; ; Constants ; ;;;;;;;;;;;;; STACK_SEGMENT EQU 09000h ; Top of conventional memory STACK_SIZE EQU 0ffffh ; 64K - 1 bytes of stack SCREEN_SEGMENT EQU 0b800h SCREEN_COLS EQU 80 SCREEN_ROWS EQU 25 KEYBOARD_INTERRUPT EQU 9