Nasm's version of start32.asm

dufrp@oricom.ca dufrp@oricom.ca
Thu, 24 Apr 1997 06:59:55 -0400


; Paul Dufresne (dufrp@oricom.ca) note:
; I have translated this code from TASM to NASM.
; Every bug is caused by me, not TRAN. :)
; In fact I just discovered that it crash after writing the registers
; to screen when an error happens. I don't feel like searching the bug,
; so I post to tunes-lll@ens.fr mailing list anyway. Please don't spread
; too much in this bad state.
; to assemble write:   nasm -f bin ex0.asm  -o ex0.com       [lowercase!]
; example0.inc is DIRECTLY included at the end of this file.

; 386 Protected mode control program header.
; By Tran.
; Feel free to use this code in your own programs.

LOWMIN  equ     0               ; minimum low memory needed to run (in K)
EXTMIN  equ     0               ; minimum extended memory needed to run (in
TSTAK   equ     400h            ; total stack size (in bytes)
ISTAK   equ     80h             ; hardware IRQ safe stack size (in bytes)

[ABSOLUTE 0]
lml     resw    1
bsl     resw    1
bsm     resb    1
acc     resb    1
lmh     resb    1
bsh     resb    1
descr_len

[ABSOLUTE 0]
back            resd      1
esp0            resd      1
sp0             resd      1     ; should be 10h
esp1            resd      1
sp1             resd      1
esp2            resd      1
sp2             resd      1
ocr3            resd      1
oeip            resd      1
oeflags         resd      1
oeax            resd      1
oecx            resd      1
oedx            resd      1
oebx            resd      1
oesp            resd      1
oebp            resd      1
oesi            resd      1
oedi            resd      1
oes             resd      1
ocs             resd      1
oss             resd      1
ods             resd      1
ofs             resd      1
ogs             resd      1
oldtr           resd      1
iomap           resd      1   ; should be 104 shl 16
task_len

[segment .text]
[org 0x100]  ; was 0 in genuine code
[BITS 16]
jmp start16
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; 16 bit basic system data
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
stak16          times 100h db 0
stak16e
oldint1b        dd      0 ; ?
old_cs          dw      0 ; ?
nullint         db      0cfh ; I think it is iret
errmsg0         db      'You must have a 386 or better to run this program!!
,7,'$'
errmsg1         db      'This system is already in V86 mode!!!',7,'$'
errmsg2         db      'You must have 640k low memory to run this program!!
,7,'$'
errmsg3         db      'Not enough extended memory to run this program!!!',
'$'
errmsg4         db      'You must have VGA to run this program!!!',7,'$'
errmsg5         db      'Not enough low memory to run this program!!!',7,'$'
defidt          dw      3ffh, 0,0

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; 16 bit basic system code
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
chek_VGA:                               ; Detect VGA or MCGA card
        xor bx,bx
        mov ax,01a00h
        int 10h
        cmp bl,7
        jb short detectvgano
        cmp bl,0ch
        ja short detectvgano
        ret
detectvgano:
        mov dx,errmsg4
        jmp exit16err
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
chek_processor:                         ; Detect if current processor 386
        pushf
        xor ah,ah
        push ax
        popf
        pushf
        pop ax
        and ah,0f0h
        cmp ah,0f0h
        je short detectno386
        mov ah,0f0h
        push ax
        popf
        pushf
        pop ax
        and ah,0f0h
        jz short detectno386
        popf
        ret
detectno386:
        mov dx,errmsg0
        jmp short exit16err
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
chek_virtual:                           ; Chek if already running in V86 mod
        smsw ax
        test al,1
        jnz short detected_virtual86
        ret
detected_virtual86:
        mov dx,errmsg1
        jmp short exit16err
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
chek_memory:                            ; Chek and get info on memory
        int 12h
        cmp ax,638
        jb short notenoughlowmem
        movzx eax,ax
        shl eax,10
        sub eax,[ds:_code32a]
        mov [ds:_lomemtop],eax
        sub eax,[ds:_lomembase]
        shr eax,10
        cmp eax,LOWMIN
        jb short notenoughlowmem2
        mov ah,88h
        int 15h
        cmp ax,EXTMIN
        jb short notenoughhighmem
        mov [ds:_totalextmem],ax
        movzx eax,ax
        shl eax,10
        add eax,[ds:_himembase]
        mov [ds:_himemtop],eax
        ret
notenoughlowmem:
        mov dx,errmsg2
        jmp short exit16err
notenoughlowmem2:
        mov dx,errmsg5
        jmp short exit16err
notenoughhighmem:
        mov dx,errmsg3
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
exit16err:                              ; Exit program with message
        mov ah,9
        int 21h
        mov ax,4cffh
        int 21h
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
init_vm86_task
        mov dword [ds:v86task+sp0],10h
        mov eax,104
        shl eax,16
        mov [ds:v86task+iomap],eax
        ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
start16:                                ; Program begins here
        cli
        mov sp,stak16e
        mov ax,cs
        mov ds,ax
        call chek_VGA
        call chek_processor
        call chek_virtual

        mov ax,cs                  ; Calc misc memory pointers (was code16)
        mov [cs:old_cs],ax
        movzx eax,ax
        shl eax,4
        mov [ds:_code16a],eax
        mov ax,cs                  ; was code32
        movzx eax,ax
        shl eax,4
        mov [ds:_code32a],eax
        mov ebx,codeend
        shl ebx,4
        sub ebx,eax
        add [ds:v86task+esp0],ebx
        add ebx,TSTAK
        mov [ds:_lomembase],ebx
        mov ebx,100000h
        sub ebx,eax
        mov [ds:_himembase],ebx
        call chek_memory

        xor ax,ax                       ; Disable CTRL+BREAK
        mov es,ax
        mov eax,[es:1bh*4]
        mov [oldint1b],eax
        mov word [es:1bh*4],nullint
        mov word [es:1bh*4+2],cs

        mov eax,[ds:_code32a]             ; Set up protected mode adresses
        add dword  [ds:gdt32a+2],eax
        add dword  [ds:idt32a+2],eax
        mov [ds:code32dsc+bsl],ax
        mov [ds:data32dsc+bsl],ax
        add [ds:v86taskdsc+bsl],ax
        shr eax,8
        mov [ds:code32dsc+bsm],ah
        mov [ds:data32dsc+bsm],ah
        add [ds:v86taskdsc+bsm],ah
        mov eax,[ds:_code16a]
        mov [ds:retrealc+bsl],ax
        mov [ds:retreald+bsl],ax
        shr eax,8
        mov [ds:retrealc+bsm],ah
        mov [ds:retreald+bsm],ah
        call init_vm86_task

        lgdt [ds:gdt32a]        ; Init protected mode
        mov eax,cr0
        or al,1
        mov cr0,eax
        db 0eah
        dw start32,8

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
v86sys:                                 ; V86 interrupt
        xor eax,eax
        xor ebx,ebx
        xor ecx,ecx
        xor edx,edx
        xor esi,esi
        xor edi,edi
        xor ebp,ebp
        mov ax,[cs:v86r_ax]
        mov bx,[cs:v86r_bx]
        mov cx,[cs:v86r_cx]
        mov dx,[cs:v86r_dx]
        mov si,[cs:v86r_si]
        mov di,[cs:v86r_di]
        mov bp,[cs:v86r_bp]
        db 0cdh
v86sysintnum    db      0
        mov [cs:v86r_ax],ax
        mov [cs:v86r_bx],bx
        mov [cs:v86r_cx],cx
        mov [cs:v86r_dx],dx
        mov [cs:v86r_si],si
        mov [cs:v86r_di],di
        mov [cs:v86r_bp],bp
        mov [cs:v86r_ds],ds
        mov [cs:v86r_es],es
        pushf
        pop ax
        mov [cs:v86r_flags],ax
        int 0fdh

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
prerealmode:                            ; 16 bit protected mode to real mode
        lidt [defidt]
        mov ax,[old_cs]
        mov [new_seg],ax
        mov eax,cr0
        and al,0feh
        mov cr0,eax

        db 0eah
        dw realmode
        new_seg dw 0
realmode:                               ; Back in real mode
        xor ax,ax                       ; Reenable CTRL+BREAK
        mov es,ax
        mov eax,[cs:oldint1b]
        mov [es:1bh*4],eax
        mov ax,cs                       ; Fix up regs and quit to DOS
        mov ds,ax
        mov es,ax
        mov ss,ax
        xor eax,eax
        mov fs,ax
        mov gs,ax
        xor ebx,ebx
        xor ecx,ecx
        xor edx,edx
        xor esi,esi
        xor edi,edi
        xor ebp,ebp
        mov esp,stak16e+200h
        mov ax,4c00h
        int 21h

        dw      0,0,0

;===========================================================================
==
;------- org 0
[BITS 32]

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; 32 bit basic system data
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
v86task         times task_len db 0 ; ?
                times 2000h db 0
gdt32           db 0x00,0x00, 0x00,0x00, 0x00, 00000000b, 00000000b, 0
code32dsc       db 0xff,0xff, 0x00,0x00, 0x00, 10011010b, 11001111b, 0
data32dsc       db 0xff,0xff, 0x00,0x00, 0x00, 10010010b, 11001111b, 0
zerodsc         db 0xff,0xff, 0x00,0x00, 0x00, 10010010b, 11001111b, 0
v86taskdsc      db 0xff,0xff
                dw v86task
                db                       0x00, 10001001b, 0, 0
retrealc        db 0xff,0xff, 0x00,0x00, 0x00, 10011010b, 0, 0
retreald        db 0xff,0xff, 0x00,0x00, 0x00, 10010010b, 0, 0
idt32           dw      exc0, 8, 08e00h, 0
                dw      exc1, 8, 08e00h, 0
                dw      exc2, 8, 08e00h, 0
                dw      exc3, 8, 08e00h, 0
                dw      exc4, 8, 08e00h, 0
                dw      exc5, 8, 08e00h, 0
                dw      exc6, 8, 08e00h, 0
                dw      exc7, 8, 08e00h, 0
                dw      exc8, 8, 08e00h, 0
                dw      exc9, 8, 08e00h, 0
                dw      exca, 8, 08e00h, 0
                dw      excb, 8, 08e00h, 0
                dw      excc, 8, 08e00h, 0
                dw      v86gen, 8, 08e00h, 0
                dw      exce, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      unexp, 8, 08e00h, 0
                dw      irq0, 8, 08e00h, 0
                dw      irq1, 8, 08e00h, 0
                dw      irq2, 8, 08e00h, 0
                dw      irq3, 8, 08e00h, 0
                dw      irq4, 8, 08e00h, 0
                dw      irq5, 8, 08e00h, 0
                dw      irq6, 8, 08e00h, 0
                dw      irq7, 8, 08e00h, 0
                dw      irq8, 8, 08e00h, 0
                dw      irq9, 8, 08e00h, 0
                dw      irqa, 8, 08e00h, 0
                dw      irqb, 8, 08e00h, 0
                dw      irqc, 8, 08e00h, 0
                dw      irqd, 8, 08e00h, 0
                dw      irqe, 8, 08e00h, 0
                dw      irqf, 8, 08e00h, 0
                dw      callv86sys, 8, 8e00h, 0
gdt32a          dw      037h, gdt32,0
idt32a          dw      187h, idt32,0

v86irqnum       db      0               ; num of IRQ that ocurred in V86 mod
v86r_ax                                 ; Virtual regs for virtual ints
v86r_al         db      0
v86r_ah         db      0
v86r_bx
v86r_bl         db      0
v86r_bh         db      0
v86r_cx
v86r_cl         db      0
v86r_ch         db      0
v86r_dx
v86r_dl         db      0
v86r_dh         db      0
v86r_si         dw      0
v86r_di         dw      0
v86r_bp         dw      0
v86r_ds         dw      0
v86r_es         dw      0
v86r_flags      dw      0

oirqm21         db      0               ; old low IRQ mask
oirqma1         db      0               ; old high IRQ mask
_totalextmem    dw      0               ; total extended memory present
_code16a        dd      0               ; offset of start of program from 0
_code32a        dd      0               ; offset of start of 32bit code from
_lomembase      dd      0               ; low mem base for allocation
_lomemtop       dd      0               ; top of low mem
_himembase      dd      0               ; high mem base for allocation
_himemtop       dd      0               ; top of high mem
_hextbl         db      '0123456789ABCDEF'

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; 32 bit basic system code
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
callv86sys:                             ; V86 INT AL
        pushad
        push es
        push fs
        push gs
        mov bx,18h
        mov es,bx
        mov ebx,[_code16a]
        mov [es:v86sysintnum+ebx],al
        push dword [v86task+esp0]
        mov ecx,esp
        sub esp,ISTAK
        mov [v86task+esp0],esp
        xor eax,eax
        push eax
        push eax
        mov ax,[v86r_ds]
        push eax
        mov ax,[v86r_es]
        push eax
        mov eax,codeend
        push eax
        shl eax,4
        sub eax,[_code32a]
        sub ecx,eax
        push ecx
        pushfd
        pop eax
        or eax,20000h
        push eax
        mov ax, word [cs:old_cs]   ; ????????????????????????????????????
        movzx eax,ax
        push eax
        mov eax,v86sys
        push eax
        iretd
retfromv86:
        mov ax,10h
        mov ds,ax
        mov esp,[v86task+esp0]
        add esp,ISTAK
        pop dword [v86task+esp0]
        pop gs
        pop fs
        pop es
        popad
        iretd
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
v86gen:                                 ; General protection violation handl
        test byte  [esp+14],2
        jnz short v86genv86
        pushad
        mov dl,13
        jmp exc
v86genv86:
        add esp,4
        pushad
        mov ax,18h
        mov ds,ax
        movzx ebx,word  [esp+36]
        shl ebx,4
        add ebx,[esp+32]
        inc word  [esp+32]
        mov al,[ebx]
        mov dl,3
        cmp al,0cch
        je short v86int
        cmp al,0ceh
        jna .L1
          jmp exc
       .L1
        je short v86genv86ni
        inc word  [esp+32]
        mov dl,[ebx+1]
        cmp dl,0fdh
        jne short v86int
        jmp retfromv86
v86genv86ni:
        mov dl,4
v86int:                                 ; Do interrupt for V86 task
        mov ax,18h
        mov ds,ax
        movzx ebx,dl
        shl ebx,2
        movzx edx,word  [esp+48]
        shl edx,4
        sub word  [esp+44],6
        add edx,[esp+44]
        mov ax,[esp+40]
        mov [edx+4],ax
        mov ax,[esp+36]
        mov [edx+2],ax
        mov ax,[esp+32]
        mov [edx],ax
        and word  [esp+40],0fcffh
        mov eax,[ds:ebx]
        mov [esp+32],ax
        shr eax,16
        mov [esp+36],ax
        popad
        iretd

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
exc0:                                   ; Exceptions
        push ax
        mov al,0
        jmp irq
exc1:
        push ax
        mov al,1
        jmp irq
exc2:
        push ax
        mov al,2
        jmp irq
exc3:
        push ax
        mov al,3
        jmp irq
exc4:
        push ax
        mov al,4
        jmp irq
exc5:
        push ax
        mov al,5
        jmp irq
exc6:
        pushad
        mov dl,6
        jmp short exc
exc7:
        push ax
        mov al,7
        jmp irq
exc8:
        pushad
        mov dl,8
        jmp short exc
exc9:
        pushad
        mov dl,9
        jmp short exc
exca:
        pushad
        mov dl,10
        jmp short exc
excb:
        pushad
        mov dl,11
        jmp short exc
excc:
        pushad
        mov dl,12
        jmp short exc
exce:
        pushad
        mov dl,14
        jmp short exc
unexp:                                  ; Unexpected interrupt
        pushad
        mov dl,0ffh
exc:
        cld                             ; Dump data
        mov ax,10h
        mov ds,ax
        mov es,ax
        mov fs,ax
        mov ax,18h
        mov gs,ax
        mov al,0ffh
        out 21h,al
        out 0a1h,al
        mov al,10h
        mov word [v86r_ax],3    ; set video mode 3
        int 30h
        mov edi,0b8000h+2*160
        sub edi,[_code32a]
        mov ebx,_hextbl
        mov ecx,2
        shl edx,24
        mov ah,0fh             ; color
        call excput
        add edi,152
        mov ah,0ah
        mov ebp,8
excl0:
        pop edx
        mov cl,8
        call excput
        dec ebp
        jnz excl0
        mov ebp,codeend
        shl ebp,4
        sub ebp,[_code32a]
        add ebp,TSTAK
excf0:
        mov ah,0ch
excl1:
        pop edx
        mov cl,8
        call excput
        cmp esp,ebp
        jbe excf0
        jmp _exit
excput:
        rol edx,4

        mov al,dl
        and al,0fh
        xlatb
        stosw
        loop excput
        mov al,' '
        stosw
        stosw
        ret

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
irq0:                                   ; Do IRQs
        push ax
        mov al,8
        jmp short irq
irq1:
        push ax
        mov al,9
        jmp short irq
irq2:
        push ax
        mov al,0ah
        jmp short irq
irq3:
        push ax
        mov al,0bh
        jmp short irq
irq4:
        push ax
        mov al,0ch
        jmp short irq
irq5:
        push ax
        mov al,0dh
        jmp short irq
irq6:
        push ax
        mov al,0eh
        jmp short irq
irq7:
        push ax
        mov al,0fh
        jmp short irq
irq8:
        push ax
        mov al,70h
        jmp short irq
irq9:
        push ax
        mov al,71h
        jmp short irq
irqa:
        push ax
        mov al,72h
        jmp short irq
irqb:
        push ax
        mov al,73h
        jmp short irq
irqc:
        push ax
        mov al,74h
        jmp short irq
irqd:
        push ax
        mov al,75h
        jmp short irq
irqe:
        push ax
        mov al,76h
        jmp short irq
irqf:
        push ax
        mov al,77h
irq:
        test byte  [esp+12],2
        jnz short v86irq
        push ds                         ; A real mode IRQ in protected mode
        push ss
        pop ds
        int 30h
        pop ds
        pop ax
        iretd
v86irq:                                 ; An IRQ from V86 mode
        mov [ss:v86irqnum],al
        pop ax
        pushad
        mov dl,[ss:v86irqnum]
        jmp v86int

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
set8529vektorz:                         ; Set new IRQ vektor numbers
        mov al,11h                      ;  BL - low vektor base #
        out 20h,al                      ;  BH - high vektor base #
        jmp short $+2
        mov al,bl
        out 21h,al
        jmp short $+2
        mov al,4h
        out 21h,al
        jmp short $+2
        mov al,1h
        out 21h,al
        jmp short $+2
        mov al,11h
        out 0a0h,al
        jmp short $+2
        mov al,bh
        out 0a1h,al
        jmp short $+2
        mov al,2h
        out 0a1h,al
        jmp short $+2
        mov al,1h
        out 0a1h,al
        ret

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
enableA20:                              ; Enable gate A20
        call enableA20o1
        jnz short enableA20done
        mov al,0d1h
        out 64h,al
        call enableA20o1
        jnz short enableA20done
        mov al,0dfh
        out 60h,al
enableA20o1:
        mov ecx,20000h
enableA20o1l:
        jmp short $+2
        in al,64h
        test al,2
        loopnz enableA20o1l
enableA20done:
        ret

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
start32:                                ; 32bit code begins here
        lidt [cs:idt32a]
        mov ax,10h
        mov ds,ax
        mov es,ax
        mov fs,ax
        mov ss,ax
        mov ax,18h
        mov gs,ax
        mov esp,[_lomembase]
        mov ax,20h
        ltr ax
        pushfd
        pop eax
        or ah,30h
        and ah,10111111b
        push eax
        popfd
        in al,21h
        mov [oirqm21],al
        or al,3
        out 21h,al
        in al,0a1h
        mov [oirqma1],al
        mov bx,2820h
        call set8529vektorz
        call enableA20
        sti  ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        jmp _main

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Some 'system' services
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Exit to real mode
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_exit:
        cli
        mov bx,7008h
        call set8529vektorz
        mov al,[oirqm21]
        out 21h,al
        mov al,[oirqma1]
        out 0a1h,al
        mov ax,30h
        mov ds,ax
        mov es,ax
        mov fs,ax
        mov gs,ax
        mov ss,ax
        db 0eah
        dw prerealmode,0,28h

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Get interrupt vektor (0-30h)
; In:
;   BL - interrupt number
; Out:
;   EAX - 32 bit offset in code
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_getvect:
        push ebx
        movzx ebx,bl
        mov ax,[idt32+ebx*8+6]
        shl eax,16
        mov ax,[idt32+ebx*8]
        pop ebx
_ret:                                   ; Generic RET for all procedures
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Set interrupt vektor (0-30h)
; In:
;   BL - interrupt number
;   EAX - 32 bit offset in code
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_setvect:
        pushf
        cli
        push eax
        push ebx
        movzx ebx,bl
        mov [idt32+ebx*8],ax
        shr eax,16
        mov [idt32+ebx*8+6],ax
        pop ebx
        pop eax
        popf
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Allocate any mem, (first cheks low, then high)
; In:
;   EAX - size requested
; Out:
;   CF=1  - not enough mem
;     EAX - ?
;   CF=0  - memory allocated
;     EAX - linear pointer to mem
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_getmem:
        push eax
        call _getlomem
        jnc short getmemd
        pop eax
        jmp short _gethimem
getmemd:
        add esp,4
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Allocate some low mem
; In:
;   EAX - size requested
; Out:
;   CF=1  - not enough mem
;     EAX - ?
;   CF=0  - memory allocated
;     EAX - linear pointer to mem
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_getlomem:
        add eax,[_lomembase]
        cmp eax,[_lomemtop]
        ja short getmemerr
        xchg eax,[_lomembase]
        clc
        ret
getmemerr:
        stc
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Allocate some high mem
; In:
;   EAX - size requested
; Out:
;   CF=1  - not enough mem
;     EAX - ?
;   CF=0  - memory allocated
;     EAX - linear pointer to mem
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_gethimem:
        add eax,[_himembase]
        cmp eax,[_himemtop]
        ja short getmemerr
        xchg eax,[_himembase]
        clc
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Get amount of free low mem
; Out:
;   EAX - number of bytes free
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_lomemsize:
        mov eax,[_lomemtop]
        sub eax,[_lomembase]
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Get amount of free high mem
; Out:
;   EAX - number of bytes free
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_himemsize:
        mov eax,[_himemtop]
        sub eax,[_himembase]
        ret

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Put '$' terminated message to DOS
; In:
;   EDX -> message in low mem
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
_putdosmsg:
        push ax
        push edx
        add edx,[_code32a]
        mov al,dl
        and ax,0fh
        shr edx,4
        mov [v86r_ds],dx
        mov [v86r_dx],ax
        mov byte [v86r_ah],9
        mov al,21h
        int 30h
        pop edx
        pop ax
        ret
;===========================================================================
;===========================================================================
;===========================================================================
; Included part
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; DATA
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
msg0            db      'Free low mem:  '
msg0len equ $-msg0
msg1            db      'Free high mem: '
msg1len equ $-msg1

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; CODE
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
_main:

        ;db 0x0f,0x50  ; What happens on an invalid opcode?
        ;@rlp edi,0b8000h                ; fill text screen with stuff
          mov edi,0b8000h
          sub edi,[_code32a]
        mov ecx,80*25
        mov al,'±'
        mov ah,78h
        rep stosw

        mov ah,0fh                      ; put amount of free low mem
        ;@rlp edi,0b8000h+2*160+4
          mov edi,0b8000h+2*160+4
          sub edi,[_code32a]
        mov esi,msg0
        mov ecx,msg0len
mainl0:
        lodsb
        stosw
        loop mainl0
        call _lomemsize
        call putnum

        ;@rlp edi,0b8000h+3*160+4        ; put amount of free high mem
          mov edi,0b8000h+3*160+4
          sub edi,[_code32a]
        mov esi,msg1
        mov ecx,msg1len
mainl1:
        lodsb
        stosw
        loop mainl1
        call _himemsize
        call putnum

; Uncomment this and the next piece of code if you have a mouse driver loade
; and want to test the handling of real-mode IRQs.
;       mov v86r_ax,0                   ; Enable and unhide mouse cursor
;       mov al,33h
;       int 30h
;       mov v86r_ax,1
;       int 30h

        mov byte [v86r_ah],0            ; INT 16h, AH=0, wait for keypress
        mov al,16h
        int 30h

;       mov v86r_ax,0                   ; Disable mouse
;       mov al,33h
;       int 30h

        jmp _exit                       ; return to real mode

;---------------------------------------------------------------------------
putnum:                                 ; put EAX to EDI
        mov edx,eax
        mov ecx,8
        mov ebx,_hextbl
        mov ah,0fh
putnuml0:
        rol edx,4
        mov al,dl
        and al,0fh
        xlatb
        stosw
        loop putnuml0
        ret
; End of included code
;==========================================================================
; The following should stay at the end of all, (I think)
stak32
codeend


Net-Tamer V 1.08X - Test Drive