User:Johnburger/Demo/Exec/Alloc/RAM
From OSDev Wiki
< User:Johnburger | Demo
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