User:Johnburger/Demo/Exec/Alloc/RAM
< User:Johnburger | Demo
Jump to navigation
Jump to search
This module contains two functions:
Exec.Alloc.RAM
This function allocates the passed-in number of bytes, and returns its linear address. Note that this RAM is not yet accessible: you need a Descriptor for that! But at least you now have the Base and Size parameters to create one.
Please note that this is a naïve implementation: it merely adds the requested size to the current top of RAM, and returns the previous value. It is intelligent enough to jump the 640 kiB to 1 MiB device/ROM/BIOS hole, but it doesn't even know where the ultimate top of RAM is! That has been left as an exercise for the reader...
Exec.Alloc.RAM.Zero
This does what it says: zeroes the passed-in number of bytes starting from the passed-in pointer.
Demo/Exec/Alloc/RAM.inc
;
; Exec/Alloc/RAM.inc
;
; This module provides RAM-related functions, such as Allocating and Zeroing
; blocks of RAM. It could use the RAM Map discovered from the BIOS during Boot,
; but that's been left as an exercise for the reader!
;
; Instead, the allocator merely keeps track of the last allocated address as a
; "high water mark", returning zero if that mark becomes greater than what's
; available. Of course, this naïve implementation merely keeps giving more and
; more - with enough intelligence to skip from RAMTop to the 1 MiB mark.
;...............................................................................
; This function allocates a block of RAM from the available pool.
; Note that it doesn't allocate a Descriptor for it, since it doesn't know
; what type it'll be, nor which Table to put it in.
;
; Also note that this implementation is NOT thread-safe. It assumes that only
; one Task will ever be accessing it at the same time. To work around that,
; either some kind of lock will be required, or atomic operations such as used
; in the 80486 (such as XADD) should be used.
;
; Input: DS = Data
; ECX = Size requested
; Output: EAX = Address of allocated RAM, or zero if insufficient.
; ECX preserved
Exec.Alloc.RAM:
MOV EAX,[Data.RAM] ; Get current high-water mark
.Retry:
LEA EDX,[EAX+ECX+0Fh] ; Get Top, rounded to paragraph
AND EDX,~0Fh ; Well, it is now!
CMP EDX,[Data.RAMTop] ; Too far?
JBE .Save ; Not yet...
MOV EAX,0010_0000h ; Skip to 1 MiB
MOV DWORD [Data.RAMTop],-1 ; And pretend the rest is ours!
JMP .Retry ; And try again
.Save:
MOV [Data.RAM],EDX ; Save new high-water mark
.End:
RET
;...............................................................................
; This function zeroes out the block of passed-in RAM.
; Input: ES = Segment to zero
; ECX = Size to zero
; EDI = Where to zero
; Output: ES and ECX preserved.
; EAX and EDI? Not so much!
Exec.Alloc.RAM.Zero:
PUSH ECX ; As promised...
CLD ; Work forwards
XOR EAX,EAX ; Store zeroes
SHR ECX,2 ; Do DWORDs initially
REP STOSD ; Zero out whole DWORDs at a time
MOV ECX,[ESP] ; Recover saved value
AND ECX,03h ; Mask off DWORDs already done
REP STOSB ; Make up any last bytes
POP ECX
RET