cpu 8086 org 0x7C00 stack: equ 0x7C00 framsz: equ 0x300 jmp init ; Data on user stack while in kernel (5 words): ; AX BP IP CS flags ; Kernel stack: ; [frame] SP SS ; BP-^ ; The start of the frame is available via BP. ; The frame is followed by a long ptr to the user stack. ; Main entry point int20h: xor ah, ah int21h: push bp push ax ; Test if SS=0, if it is, we assume we are already on kernel stack mov ax, ss test ax, ax jz rentry ; Save user stack mov ax, ss mov [cs:stack-2], ax mov [cs:stack-4], sp ; Set up kernel stack xor ax, ax mov ss, ax mov sp, (stack-4) jmp scall ; This is like the above, except that it doesnt switch stacks. ; The 'user' stack data is after (below on stack) the kernel frame. ; [frame] SP SS AX BP IP CS flags ; \-\--^ rentry: mov ax, sp push ss push ax scall: sub sp, framsz mov bp, sp call getax call jmptab ; Restore user stack mov sp, [bp+framsz] mov ax, [bp+framsz+2] mov ss, ax pop ax pop bp iret ; Lookup address of subfunction ; Mesh up the stack so we return to subfunction ; and subfunction later returns to scall jmptab: push ax push bx xor bx, bx add bl, ah add bl, ah mov bx, [cs:bx+sftab] mov [bp-4], bx pop bx ret ; Get AX from the user stack getax: push ds push si lds si, [bp+framsz] lodsw pop ds pop si ret ; No such subfunction - set carry and exit sferr: stc ret ; Subfunction table sftab: dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr ; 10 dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr ; 20 dw sferr, sferr, sferr, sferr dw sferr, setint, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr ; 30 dw sferr, sferr, sferr, sferr dw sferr, getint, sferr, sferr dw sferr, sferr, sferr, sferr dw sferr, sferr, sferr, sferr ; IN al number ; OUT bx al * 4 times4: push ax xor ah, ah add al, al add al, al mov bx, ax pop ax ret ; DOS 2+ - GET INTERRUPT VECTOR ; IN al interrupt number ; OUT es:bx current interrupt handler getint: push ds ; DS=0 xor bx, bx mov ds, bx ; BX=AL*4 call times4 les bx, [bx] pop ds ret ; DOS 25h: Set interrupt vector ; IN al interrupt number ; ds:dx entry point setint: push es push bx ; ES=0 xor bx, bx mov es, bx ; BX=AL*4 call times4 mov [es:bx], dx mov ax, ds mov [es:bx+2], ds pop bx pop es ret ; ===== end of resident, begin of transient startup code init: xor ax, ax mov ds, ax mov es, ax mov ax, 0x1000 mov ss, ax xor sp, sp mov al, 0x21 mov dx, int21h call setint mov ax, 0x2520 mov dx, int20h int 0x21 mov ax, 0x3520 int 0x21 mov ah, 0x3f int 3 int 0x21 int 3 main: push cs pop ds mov si, msg mov ah, 0x0e xor bx, bx loop: lodsb test al, al jz end int 0x10 jmp loop end: hlt jmp end msg: db "rdos kernel stub", 0x0A, 0x0D, 0