759 lines
14 KiB
NASM
759 lines
14 KiB
NASM
|
|
;Affiche le nombre hexa dans %0[dword]
|
|
proc biosprinth uses ax bx cx edx si di, num:dword
|
|
mov edx,[num]
|
|
mov ah,09h
|
|
mov di,8
|
|
.hexaize:
|
|
rol edx,4
|
|
mov si,dx
|
|
and si,1111b
|
|
mov al,[cs:si+.tab]
|
|
mov cx,1
|
|
cmp al,32
|
|
jb .control
|
|
mov bx,7
|
|
mov ah,09h
|
|
int 10h
|
|
.control:
|
|
mov ah,0Eh
|
|
int 10h
|
|
dec di
|
|
jnz .hexaize
|
|
ret
|
|
.tab db '0123456789ABCDEF'
|
|
endp
|
|
|
|
;Affiche le texte ASCIIZ pointé par %0
|
|
proc biosprint uses ax bx cx si, pointer:word
|
|
mov si,[pointer]
|
|
mov cx,1
|
|
mov bx,7
|
|
.again:
|
|
lodsb
|
|
or al,al
|
|
jz .fin
|
|
cmp al,32
|
|
jb .control
|
|
mov ah,09h
|
|
int 10h
|
|
.control:
|
|
mov ah,0Eh
|
|
int 10h
|
|
jmp .again
|
|
.fin:
|
|
ret
|
|
endp
|
|
|
|
proc enablea20 uses ax
|
|
mov al,0d1h
|
|
out 64h,al
|
|
call a20wait
|
|
mov al,0dfh
|
|
out 60h,al
|
|
call a20wait
|
|
;mov al,0ffh
|
|
;out 64h,al
|
|
;call a20wait
|
|
ret
|
|
endp
|
|
|
|
proc disablea20 uses ax
|
|
mov al,0d1h
|
|
out 64h,al
|
|
call a20wait
|
|
mov al,0DDh
|
|
out 60h,al
|
|
call a20wait
|
|
;mov al,0ffh
|
|
;out 64h,al
|
|
;call a20wait
|
|
ret
|
|
endp
|
|
|
|
a20wait:
|
|
in al,64h
|
|
jmp .suite
|
|
.suite:
|
|
and al,2
|
|
jnz a20wait
|
|
ret
|
|
;par le system control port A
|
|
;in al,92h
|
|
;or al,2
|
|
;out 92h,al
|
|
|
|
;par le system control port A
|
|
;in al,92h
|
|
;and al,not 2
|
|
;out 92h,al
|
|
|
|
proc flatmode uses eax bx ds
|
|
push cs
|
|
pop ds
|
|
; first, calculate the linear address of GDT
|
|
xor eax,eax
|
|
mov ax,ds
|
|
shl eax,4
|
|
add dword [.gdt+2],eax ; store as GDT linear base addr
|
|
; now load the GDT into the GDTR
|
|
lgdt fword [.gdt] ; load GDT base
|
|
virtual at 0
|
|
.descriptor descriptor
|
|
end virtual
|
|
mov bx,1 * .descriptor.sizeof ; point to first descriptor
|
|
cli ; turn off interrupts
|
|
mov eax,cr0 ; prepare to enter protected mode
|
|
or al,1 ; flip the PE bit
|
|
mov cr0,eax ; we're now in protected mode
|
|
jmp .suite
|
|
.suite:
|
|
mov fs,bx ; load the FS segment register
|
|
and al,0FEh ; clear the PE bit again
|
|
mov cr0,eax ; back to real mode
|
|
jmp .suite2
|
|
.suite2:
|
|
sti ; resume handling interrupts
|
|
ret ;
|
|
|
|
.gdt:
|
|
gdtitse descriptor .gdtend - .gdt - 1, .gdt, 0, 0, 0, 0 ; the GDT itself
|
|
gdtdata descriptor 0ffffh, 0, 0, 091h, 0cfh, 0 ; 4G data segment
|
|
.gdtend:
|
|
endp
|
|
|
|
;Attend l'appuie sur une touche
|
|
proc bioswaitkey uses ax
|
|
xor ax,ax
|
|
int 16h
|
|
ret
|
|
endp
|
|
|
|
firstmb dw 0
|
|
|
|
|
|
;Charge les sections du block %0
|
|
proc mbloadsection uses ax bx cx si di ds es, blocks:word
|
|
mov ax,[blocks]
|
|
mov es,ax
|
|
mov ds,ax
|
|
cmp word [0],"EC"
|
|
jne .notace
|
|
lea si,[.toresov]
|
|
mov word [ss:si],0FFFFh
|
|
virtual at 0
|
|
.exe exe
|
|
end virtual
|
|
mov bx,[ds:.exe.sections]
|
|
cmp bx,0
|
|
je .finishloading
|
|
.loading:
|
|
cmp dword [bx],0
|
|
je .finishloading
|
|
mov ax,bx
|
|
add ax,4
|
|
pushad
|
|
stdcall biosprint,ax
|
|
popad
|
|
stdcall mbcreate,ax,word [bx+2]
|
|
jc .error
|
|
inc si
|
|
inc si
|
|
mov [ss:si],ax
|
|
push si
|
|
mov si,[bx]
|
|
xor di,di
|
|
mov es,ax
|
|
mov cx,[bx+2]
|
|
cld
|
|
rep movsb
|
|
pop si
|
|
add bx,4
|
|
.gonext:
|
|
inc bx
|
|
cmp byte [bx],0
|
|
jne .gonext
|
|
inc bx
|
|
jmp .loading
|
|
.finishloading:
|
|
cmp word [ss:si],0FFFFh
|
|
je .finishdepands
|
|
stdcall mbloadfuncs,word [ss:si]
|
|
jc .depandserror
|
|
dec si
|
|
dec si
|
|
jmp .finishloading
|
|
.finishdepands:
|
|
ret
|
|
.notace:
|
|
stc
|
|
ret
|
|
.error:
|
|
stc
|
|
ret
|
|
.depandserror:
|
|
stc
|
|
ret
|
|
.toresov dw 60 dup (0)
|
|
endp
|
|
|
|
|
|
;Initialise les blocs de mémoire en prenant memorystart pour segment de base
|
|
proc mbinit uses ax cx si di ds es
|
|
cmp [cs:firstmb],0
|
|
jne .alreadyok
|
|
push cs
|
|
pop ds
|
|
mov [cs:firstmb],memorystart
|
|
mov ax,memorystart-2
|
|
mov es,ax
|
|
mov si,afree
|
|
xor di,di
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
mov cx,.mb.sizeof
|
|
rep movsb
|
|
clc
|
|
ret
|
|
.alreadyok:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
afree mb "HN",0,0,0,0A000h-memorystart,"Libre"
|
|
db 0
|
|
|
|
;Creér un bloc de nom %0 de taille %1 (octets) -> n°segment dans AX
|
|
proc mbcreate uses bx cx dx si di ds es, blocks:word, size:word
|
|
push gs
|
|
mov ax,[ss:bp+4]
|
|
mov dx,ax
|
|
dec dx
|
|
dec dx
|
|
mov gs,dx
|
|
cmp word [gs:0x0],'NH'
|
|
je .oktoset
|
|
mov ax,memorystart
|
|
.oktoset:
|
|
mov gs,ax
|
|
mov cx,[size]
|
|
shr cx,4
|
|
inc cx
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
mov dl,true
|
|
.searchfree:
|
|
cmp dl,false
|
|
je .notenougtmem
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
cmp [es:.mb.isnotlast],true
|
|
sete dl
|
|
cmp [es:.mb.reference],free
|
|
jne .notsogood
|
|
mov ax,[es:.mb.sizes]
|
|
cmp cx,ax
|
|
ja .notsogood
|
|
mov word [es:.mb.check],"NH"
|
|
mov [es:.mb.isnotlast],true
|
|
mov [es:.mb.reference],gs
|
|
mov [es:.mb.isresident],false
|
|
lea di,[es:.mb.names]
|
|
push cx
|
|
mov cx,24/4
|
|
mov si,[blocks]
|
|
cld
|
|
rep movsd
|
|
pop cx
|
|
inc bx
|
|
inc bx
|
|
sub ax,cx
|
|
cmp ax,0
|
|
je .nofree
|
|
dec ax
|
|
dec ax
|
|
mov [es:.mb.sizes],cx
|
|
add cx,bx
|
|
mov es,cx
|
|
mov si,afree
|
|
xor di,di
|
|
mov cx,.mb.sizeof
|
|
push cs
|
|
pop ds
|
|
cld
|
|
rep movsb
|
|
mov [es:.mb.isnotlast],dl
|
|
mov [es:.mb.sizes],ax
|
|
.nofree:
|
|
mov ax,bx
|
|
pop gs
|
|
clc
|
|
ret
|
|
.notsogood:
|
|
inc bx
|
|
inc bx
|
|
add bx,[es:.mb.sizes]
|
|
jmp .searchfree
|
|
.memoryerror:
|
|
pop gs
|
|
stc
|
|
ret
|
|
.notenougtmem:
|
|
pop gs
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Libère le bloc de mémoire %0 et ses sous blocs
|
|
proc mbfree uses ax bx cx si di ds es, blocks:word
|
|
mov bx,[blocks]
|
|
mov ax,bx
|
|
dec bx
|
|
dec bx
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
cmp [es:.mb.reference],free
|
|
je .wasfree
|
|
cmp [es:.mb.isresident],true
|
|
je .wasresident
|
|
mov [es:.mb.reference],free
|
|
push cs
|
|
pop ds
|
|
mov si,.isfree
|
|
lea di,[es:.mb.names]
|
|
mov cx,6
|
|
cld
|
|
rep movsb
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
.searchtofree:
|
|
mov es,bx
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
inc bx
|
|
inc bx
|
|
add bx,[es:.mb.sizes]
|
|
cmp [es:.mb.sizes],0
|
|
je .nottofree
|
|
cmp ax,[es:.mb.reference]
|
|
jne .nottofree
|
|
mov [es:.mb.isresident],false
|
|
mov [es:.mb.reference],free
|
|
mov si,.isfree
|
|
lea di,[es:.mb.names]
|
|
mov cx,6
|
|
cld
|
|
rep movsb
|
|
.nottofree:
|
|
cmp [es:.mb.isnotlast],true
|
|
je .searchtofree
|
|
stdcall mbclean
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
.wasfree:
|
|
stc
|
|
ret
|
|
.wasresident:
|
|
stc
|
|
ret
|
|
|
|
.isfree db "libre",0
|
|
endp
|
|
|
|
;Mise a nivo de la mémoire (jonction de blocs libre)
|
|
proc mbclean uses ax bx dx es gs
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
xor ax,ax
|
|
xor dx,dx
|
|
.searchfree:
|
|
mov gs,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [gs:.mb.check],"NH"
|
|
jne .memoryerror
|
|
inc bx
|
|
inc bx
|
|
add bx,[gs:.mb.sizes]
|
|
cmp word [gs:.mb.sizes],0
|
|
je .notenougtmem
|
|
cmp [gs:.mb.reference],free
|
|
jne .notfree
|
|
cmp ax,0
|
|
je .notmeetfree
|
|
add dx,[gs:.mb.sizes]
|
|
mov word [gs:.mb.check],0
|
|
mov dword [gs:.mb.names],0
|
|
inc dx
|
|
inc dx
|
|
jmp .nottrigered
|
|
.notmeetfree:
|
|
xor dx,dx
|
|
mov ax,gs
|
|
jmp .nottrigered
|
|
.notfree:
|
|
cmp ax,0
|
|
je .nottrigered
|
|
mov es,ax
|
|
add [es:.mb.sizes],dx
|
|
xor ax,ax
|
|
.nottrigered:
|
|
cmp [gs:.mb.isnotlast],true
|
|
je .searchfree
|
|
cmp ax,0
|
|
je .reallyfinish
|
|
mov es,ax
|
|
add [es:.mb.sizes],dx
|
|
mov [es:.mb.isnotlast],false
|
|
.reallyfinish:
|
|
clc
|
|
ret
|
|
.notenougtmem:
|
|
stc
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Rend le segment %0 résident
|
|
proc mbresident uses bx es, blocks:word
|
|
mov bx,[blocks]
|
|
dec bx
|
|
dec bx
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
mov [es:.mb.isresident],true
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Rend le segment %0 non résident
|
|
proc mbnonresident uses bx es, blocks:word
|
|
mov bx,[blocks]
|
|
dec bx
|
|
dec bx
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
mov [es:.mb.isresident],false
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
|
|
;Change le proprietaire de %0 a %1
|
|
proc mbchown uses bx dx es,blocks:word, owner:word
|
|
mov bx,[blocks]
|
|
dec bx
|
|
dec bx
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
cmp [es:.mb.reference],free
|
|
je .wasfree
|
|
mov dx,[owner]
|
|
mov [es:.mb.reference],dx
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
.wasfree:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Alloue un bloc /data de CX caractere pour le process appelant -> ax
|
|
proc mballoc uses si ds, size:word
|
|
push cs
|
|
pop ds
|
|
stdcall mbcreate,.data,[size]
|
|
stdcall mbchown,ax,word [ss:bp+4]
|
|
ret
|
|
|
|
.data db '/data',0
|
|
endp
|
|
|
|
;Renvoie en AX le MB n° %0 carry quand terminé
|
|
proc mbget uses bx dx es, num:word
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
xor dx,dx
|
|
.searchfree:
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
inc bx
|
|
inc bx
|
|
add bx,[es:.mb.sizes]
|
|
cmp [es:.mb.sizes],0
|
|
je .memoryerror
|
|
cmp dx,[num]
|
|
je .foundmcb
|
|
ja .notfound
|
|
inc dx
|
|
cmp [es:.mb.isnotlast],true
|
|
je .searchfree
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
.foundmcb:
|
|
mov ax,es
|
|
inc ax
|
|
inc ax
|
|
clc
|
|
ret
|
|
.notfound:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Renvoie en AX le MCB qui correspond a ds:%0
|
|
proc mbfind uses bx si di es, blocks:word
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
mov si,[blocks]
|
|
.search:
|
|
mov es,bx
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
lea di,[es:.mb.names]
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
inc bx
|
|
inc bx
|
|
add bx,[es:.mb.sizes]
|
|
cmp [es:.mb.sizes],0
|
|
je .memoryerror
|
|
push si di
|
|
.cmpnames:
|
|
mov al,[es:di]
|
|
cmp al,[ds:si]
|
|
jne .ok
|
|
cmp al,0
|
|
je .ok
|
|
inc si
|
|
inc di
|
|
jmp .cmpnames
|
|
.ok:
|
|
pop di si
|
|
je .foundmcb
|
|
cmp [es:.mb.isnotlast],true
|
|
je .search
|
|
.notfound:
|
|
stc
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
.foundmcb:
|
|
mov ax,es
|
|
inc ax
|
|
inc ax
|
|
clc
|
|
ret
|
|
endp
|
|
|
|
|
|
;Renvoie en AX le sous mcb qui correspond a %0 et qui appartien a %1
|
|
proc mbfindsb uses bx dx si di es, blocks:word, owner:word
|
|
mov bx,[cs:firstmb]
|
|
dec bx
|
|
dec bx
|
|
mov si,[blocks]
|
|
virtual at 0
|
|
.mb mb
|
|
end virtual
|
|
lea di,[es:.mb.names]
|
|
mov dx,[owner]
|
|
.search:
|
|
mov es,bx
|
|
cmp word [es:.mb.check],"NH"
|
|
jne .memoryerror
|
|
inc bx
|
|
inc bx
|
|
add bx,[es:.mb.sizes]
|
|
cmp [es:.mb.sizes],0
|
|
je .memoryerror
|
|
push si di
|
|
.cmpnames:
|
|
mov al,[es:di]
|
|
cmp al,[ds:si]
|
|
jne .ok
|
|
cmp al,0
|
|
je .ok
|
|
inc si
|
|
inc di
|
|
jmp .cmpnames
|
|
.ok:
|
|
pop di si
|
|
jne .notfoundmcb
|
|
cmp [es:.mb.reference],dx
|
|
je .foundmcb
|
|
.notfoundmcb:
|
|
cmp [es:.mb.isnotlast],true
|
|
je .search
|
|
.notfound:
|
|
stc
|
|
ret
|
|
.foundmcb:
|
|
mov ax,es
|
|
inc ax
|
|
inc ax
|
|
clc
|
|
ret
|
|
.memoryerror:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
;Resouds les dépendances du bloc de mémoire %0
|
|
proc mbloadfuncs uses ax bx cx dx si ds, blocks:word
|
|
mov ds,[blocks]
|
|
cmp word [0],"EC"
|
|
jne .notace
|
|
virtual at 0
|
|
.exe exe
|
|
end virtual
|
|
mov si,[ds:.exe.imports]
|
|
cmp si,0
|
|
je .endofloading
|
|
.loadfuncs:
|
|
cmp word [si],0
|
|
je .endofloading
|
|
stdcall mbsearchfunc,si
|
|
jnc .toendoftext
|
|
mov bx,si
|
|
;pushad
|
|
;stdcall biosprint,si
|
|
;popad
|
|
.findend:
|
|
inc bx
|
|
cmp byte [bx], ':'
|
|
jne .findend
|
|
mov byte [bx],0
|
|
invoke projfile,si
|
|
mov byte [bx],':'
|
|
jc .erroronload
|
|
;pushad
|
|
;stdcall biosprint,si
|
|
;popad
|
|
stdcall mbsearchfunc,si
|
|
jc .libnotexist
|
|
.toendoftext:
|
|
mov cl,[si]
|
|
cmp cl,0
|
|
je .oktonext
|
|
inc si
|
|
jmp .toendoftext
|
|
.oktonext:
|
|
inc si
|
|
mov [si],ax
|
|
mov [si+2],dx
|
|
add si,4
|
|
jmp .loadfuncs
|
|
.endofloading:
|
|
clc
|
|
ret
|
|
.notace:
|
|
stc
|
|
ret
|
|
.libnotexist:
|
|
stc
|
|
ret
|
|
.erroronload:
|
|
stc
|
|
ret
|
|
endp
|
|
|
|
|
|
;Recherche une fonction pointé par DS:%0 en mémoire et renvoie son adresse en DX:AX
|
|
proc mbsearchfunc uses bx si di es, func:word
|
|
mov bx,[func]
|
|
mov si,bx
|
|
.findend:
|
|
virtual at 0
|
|
.exe exe
|
|
end virtual
|
|
inc bx
|
|
cmp byte [bx], ':'
|
|
jne .findend
|
|
mov byte [bx],0
|
|
stdcall mbfind,si
|
|
mov byte [bx],':'
|
|
jc .notfoundattallthesb
|
|
mov es,ax
|
|
cmp word [es:.exe.checks],"EC"
|
|
jne .notfoundattallthesb
|
|
mov di,[es:.exe.exports]
|
|
inc bx
|
|
inc bx
|
|
.functions:
|
|
cmp word [es:di],0
|
|
je .notfoundattallthesb
|
|
mov si,bx
|
|
.cmpnamesfunc:
|
|
mov al,[es:di]
|
|
cmp al,[ds:si]
|
|
jne .notfoundthesb
|
|
cmp al,0
|
|
je .seemsok
|
|
inc si
|
|
inc di
|
|
jmp .cmpnamesfunc
|
|
.notfoundthesb:
|
|
mov al,[es:di]
|
|
cmp al,0
|
|
je .oktonext
|
|
inc di
|
|
jmp .notfoundthesb
|
|
.oktonext:
|
|
inc di
|
|
inc di
|
|
inc di
|
|
jmp .functions
|
|
.seemsok:
|
|
mov dx,es
|
|
mov ax,[es:di+1]
|
|
clc
|
|
ret
|
|
.notfoundattallthesb:
|
|
stc
|
|
ret
|
|
endp
|