419 lines
8.9 KiB
NASM
419 lines
8.9 KiB
NASM
;NXOS
|
||
;Written by: Alberto Venturini (Alb‚) - 2001
|
||
;Email address: -albe-@libero.it
|
||
|
||
;Modulo aggiuntivo di gestione della memoria
|
||
;Questo modulo cambia la modalit… del processore da
|
||
;Real mode 16-bit a Real mode 32-bit.
|
||
;In questo modo si ha accesso a taaaanta memoria (64 Mbyte
|
||
;al massimo...ma direi che sono pi— che sufficienti!)
|
||
;e si ha comunque compatibilit… con la real mode 16-bit.
|
||
|
||
;Questo file va assemblato con tasm32.exe e linkato con un
|
||
;linker che supporti l'output in flat binary (".bin") (ad
|
||
;esempio elink.exe).
|
||
|
||
StartingOffset equ 120000h ;Offset a partire dal quale Š disponibile
|
||
;la memoria utente
|
||
TableOffset equ 110000h ;Offset della tabella per l'allocazione
|
||
|
||
.386p
|
||
|
||
Code Segment Para Public Use16
|
||
Assume CS:Code
|
||
|
||
org 0h
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
Main:
|
||
;Installazione del driver
|
||
cli
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov ax,offset Int2fh
|
||
mov es:[2fh*4],ax
|
||
mov ax,cs
|
||
mov es:[2fh*4+2],ax
|
||
|
||
call Real32Init
|
||
|
||
mov ah,02h
|
||
mov bl,1
|
||
int 20h
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
Int2fh:
|
||
cmp ah,00h
|
||
je Int2fh_00h
|
||
cmp ah,01h
|
||
je Int2fh_01h
|
||
cmp ah,02h
|
||
je Int2fh_02h
|
||
cmp ah,03h
|
||
je Int2fh_03h
|
||
cmp ah,04h
|
||
je Int2fh_04h
|
||
cmp ah,05h
|
||
je Int2fh_05h
|
||
iret
|
||
|
||
Int2fh_00h:
|
||
call Real32Init
|
||
iret
|
||
Int2fh_01h:
|
||
call Real32End
|
||
iret
|
||
Int2fh_02h:
|
||
call XMS_Avail
|
||
iret
|
||
Int2fh_03h:
|
||
call MemAlloc32
|
||
iret
|
||
Int2fh_04h:
|
||
call MemoryLeft
|
||
iret
|
||
Int2fh_05h:
|
||
call MemFree32
|
||
iret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
Real32Init:
|
||
;Inizializza la Real Mode a 32 bit
|
||
;no Input, no Output
|
||
pusha
|
||
|
||
call Check_Safety ;giusto per sicurezza, anche se non dovrebbero
|
||
;esserci errori.
|
||
test ax,ax
|
||
jnz Real32Init_Error
|
||
|
||
call Enable_A20 ;Inizializza la 32bit real mode
|
||
call Pmode
|
||
|
||
call XMS_Avail ;Calcola la memoria totale
|
||
cmp ax,128
|
||
jbe Real32Init_Error
|
||
|
||
mov word ptr cs:[TotalMemory],ax ;Mettiamo la memoria totale in
|
||
;questa variabile
|
||
|
||
Real32Init_PrepareTable:
|
||
mov cx,ax ;In AX ho il numero totale di Kbytes presenti.
|
||
;Inizializza il valore corrispondente a questi
|
||
;Kbytes a zero.
|
||
sub cx,64 ;Toglie 64 (perchŠ Š primi 64 kbytes sono occupati
|
||
;dalla tabella di allocazione della memoria).
|
||
mov ax,0
|
||
mov es,ax
|
||
mov edi,TableOffset
|
||
|
||
Real32Init_Table2:
|
||
;Azzera tutte le posizioni nella tabella di allocazione della memoria
|
||
mov es:[edi],al ;Nota: non funziona il "tradizionale" stosb...
|
||
inc edi
|
||
loop Real32Init_Table2
|
||
|
||
popa
|
||
|
||
ret
|
||
|
||
Real32Init_Error:
|
||
|
||
call Disable_A20
|
||
|
||
popa
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
Real32End:
|
||
;Termina la Real Mode a 32 bit
|
||
push ax
|
||
call Disable_A20
|
||
pop ax
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
MemAlloc32:
|
||
;Input DX=numero di Kbytes da allocare
|
||
;Output EDI=offset a partire dal quale Š disponibile la memoria
|
||
|
||
push ax
|
||
push cx
|
||
push dx
|
||
push es
|
||
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov edi,TableOffset ;edi punta alla tabella di allocazione memoria
|
||
|
||
MemAlloc32_CheckSingle:
|
||
;Esegue questo ciclo finchŠ non trova un valore uguale a 0 (cioŠ un Kbyte
|
||
;libero).
|
||
mov al,es:[edi]
|
||
inc edi
|
||
cmp di,cs:[TotalMemory]
|
||
jae MemAlloc32_MemoryNotFound
|
||
test al,al
|
||
jnz MemAlloc32_CheckSingle
|
||
|
||
MemAlloc32_CheckTotal:
|
||
mov cx,dx
|
||
dec cx
|
||
|
||
MemAlloc32_CheckTotal2:
|
||
;Controlla se ci sono abbastanza Kbytes contigui liberi
|
||
test cx,cx
|
||
jz MemAlloc32_MemoryFound
|
||
mov al,es:[edi]
|
||
inc edi
|
||
cmp di,cs:[TotalMemory]
|
||
jae MemAlloc32_MemoryNotFound
|
||
dec cx
|
||
test al,al
|
||
jz MemAlloc32_CheckTotal2
|
||
|
||
jmp MemAlloc32_CheckSingle
|
||
|
||
MemAlloc32_MemoryFound:
|
||
sub di,dx
|
||
mov al,1
|
||
|
||
push edi
|
||
|
||
MemAlloc32_MemoryFound2:
|
||
;Occupa la memoria!
|
||
mov es:[edi],al
|
||
inc edi
|
||
dec dx
|
||
jnz MemAlloc32_MemoryFound2
|
||
|
||
pop edi
|
||
|
||
;Conversione di EDI: da indice nella tabella di allocazione a offset
|
||
and edi,0000FFFFh
|
||
|
||
shl edi,10 ;converte il risultato in Kbytes
|
||
|
||
add edi,StartingOffset
|
||
|
||
pop es
|
||
pop dx
|
||
pop cx
|
||
pop ax
|
||
|
||
ret
|
||
|
||
MemAlloc32_MemoryNotFound:
|
||
;[...]
|
||
|
||
pop es
|
||
pop dx
|
||
pop cx
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
MemoryLeft:
|
||
;questa procedura ritorna la memoria libera disponibile.
|
||
;CX=numero di Kbytes *contigui* liberi
|
||
;DX=numero di Kbytes *totali* liberi
|
||
|
||
push ax
|
||
push bx
|
||
push es
|
||
push edi
|
||
|
||
mov edi,TableOffset
|
||
xor ax,ax
|
||
mov dx,ax
|
||
mov bx,ax
|
||
mov es,ax
|
||
|
||
MemoryLeft_1:
|
||
mov al,es:[edi]
|
||
inc edi
|
||
cmp di,cs:[TotalMemory]
|
||
je MemoryLeft_End
|
||
test al,al
|
||
jnz MemoryLeft_1
|
||
|
||
inc dx
|
||
mov cx,1
|
||
|
||
MemoryLeft_2:
|
||
mov al,es:[edi]
|
||
inc edi
|
||
cmp di,cs:[TotalMemory]
|
||
je MemoryLeft_End2
|
||
test al,al
|
||
jnz MemoryLeft_3
|
||
inc cx
|
||
inc dx
|
||
jmp MemoryLeft_2
|
||
|
||
MemoryLeft_3:
|
||
cmp cx,bx
|
||
jbe MemoryLeft_1
|
||
mov bx,cx
|
||
jmp MemoryLeft_1
|
||
|
||
MemoryLeft_End2:
|
||
cmp cx,bx
|
||
jbe MemoryLeft_End
|
||
mov bx,cx
|
||
|
||
MemoryLeft_End:
|
||
pop edi
|
||
pop es
|
||
pop bx
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
MemFree32:
|
||
;input EDI=offset a partire dal quale va liberata la memoria
|
||
;DX=numero di Kbytes da liberare
|
||
|
||
push ax
|
||
push dx
|
||
push es
|
||
push edi
|
||
|
||
sub edi,StartingOffset
|
||
shr edi,10
|
||
|
||
add edi,TableOffset
|
||
|
||
xor ax,ax
|
||
mov es,ax
|
||
|
||
MemFree32_1:
|
||
mov es:[edi],al
|
||
inc edi
|
||
dec dx
|
||
jnz MemFree32_1
|
||
|
||
pop edi
|
||
pop es
|
||
pop dx
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
;Il codice sotto l'ho preso da un file di Alexei A. Frounze
|
||
;Il file originale si chiama "4gb.zip" ed Š scaricabile dal
|
||
;sito dell'autore: http://www.chat.ru/~alexfru
|
||
|
||
;--------------------------- A20 line switching ----------------------------
|
||
|
||
Enable_A20:
|
||
Mov AL, 0D1h
|
||
Out 64h, AL
|
||
Mov AL, 0DFh
|
||
Out 60h, AL
|
||
Ret
|
||
|
||
Disable_A20:
|
||
Mov AL, 0D1h
|
||
Out 64h, AL
|
||
Mov AL, 0DDh
|
||
Out 60h, AL
|
||
Ret
|
||
|
||
;----------- Checking processor mode and looking for Himem.sys -------------
|
||
|
||
Check_Safety:
|
||
SMSW CS:XXX
|
||
Mov AX, CS:XXX
|
||
And AX, 1
|
||
JNZ @@CSQ ; 1 - Processor is in Protected Mode
|
||
@@CSQ:
|
||
Ret
|
||
XXX DW ?
|
||
|
||
;------------------------- Getting XMS ammount -----------------------------
|
||
|
||
Read_CMOS:
|
||
Out 70h, AL ; CMOS address should be stored in the AL register
|
||
Jmp @@RCW ; Little delay
|
||
@@RCW:
|
||
In AL, 71h ; AL = value
|
||
Ret
|
||
|
||
|
||
XMS_Avail:
|
||
;Output AX=memoria disponibile (con un massimo di circa 64Mb,
|
||
;perchŠ Š una word...)
|
||
;Questa funzione restituisce la memoria XMS disponibile.
|
||
|
||
Mov AL, 31h ; 31h = hi byte address
|
||
Call Read_CMOS
|
||
Mov AH, AL
|
||
Mov AL, 30h ; 30h = low byte address
|
||
Call Read_CMOS ; AX = XMS installed above 1MB (in Kilobytes)
|
||
sub ax,128 ;toglie 128 perchŠ la memoria disponibile inizia da 120000h
|
||
ret
|
||
|
||
;-------- Protected mode intialization and creation of 4GB segment ---------
|
||
|
||
PMode:
|
||
Xor EAX, EAX
|
||
Mov AX, CS
|
||
Shl EAX, 4
|
||
LEA EDX, GDT
|
||
Add EAX, EDX
|
||
Mov DWord Ptr CS:GDTR+2, EAX; Fill in GDTR with physical address
|
||
; of Global Descriptor Table
|
||
Push DS
|
||
CLI
|
||
LGDT FWord Ptr CS:GDTR ; Load Global Descriptor Table
|
||
Mov EAX, 1
|
||
Mov CR0, EAX ; Set Protected Mode
|
||
Mov AX, 8
|
||
Mov DS, AX
|
||
Mov ES, AX
|
||
Mov FS, AX
|
||
Mov GS, AX ; All segment registers are loaded
|
||
; with 4GB segment's selector
|
||
Xor EAX, EAX
|
||
Mov CR0, EAX ; Set Real Mode
|
||
STI
|
||
Pop DS
|
||
|
||
;----------------------------------------------------------;
|
||
; Now you can access all the memory by putting zero to a ;
|
||
; segment register and 32bit physical address to an index ;
|
||
; register. ;
|
||
; -= Simple example =- ;
|
||
; Xor AX, AX ;
|
||
; Mov ES, AX ; zero the ES register ;
|
||
; Mov EDI, 1024*1024+65536 ; 1st byte we can use freely ;
|
||
; Mov BL, Byte Ptr ES:[EDI] ; read byte ;
|
||
; Mov DWord Ptr ES:[EDI], EDX ; write dword ;
|
||
;----------------------------------------------------------;
|
||
|
||
Ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GDT DQ 0, 8F92000000FFFFh ; "0" & "4GB" Descriptors
|
||
GDTR DW 16, 0, 0
|
||
|
||
TotalMemory dw ?
|
||
Errormsg db 'An error occurred while switching to 32-bit real mode',13,10,0
|
||
|
||
Code EndS
|
||
|
||
End
|