--- /dev/null
+SYSTEM SERVICES LAYOUT
+======================
+
+All OS functionality can be reached from one or several
+interfaces/services.
+
+When calling the system interrupt 0x32, you request a service
+number and function in AX register with AL & AH. Making 256 the max
+number of interfaces and available service-functions.
+
+Services numbered 0x0F and below are system reserved and will not be
+assigned automatically when requesting to add a new service. They can
+still be replaced by implicitly requesting that service number instead
+of getting a free one assigned.
+
+This will allow for great OS modularity when each interface/service-
+group can be replaced or upgraded by any user software or driver.
+
+Most service groups or interfaces can be extended with drivers for
+the type of device(s) that it handles, or the full service/interface
+can be replaced for more fundamental changes to the design. For
+example the 'process' and 'memory' interfaces can be replaced to
+allow more advanced functionality like multitasking and paging.
+
+The OS will be unable to function at all without the basic service
+0x00 that performs the most crucial tasks, and without the STDIO and
+VFS interfaces it will be severly crippled, left with no means of
+communication, except perhaps a beep or two from the PC-speaker.
+
+Below is a more visual representation of the main OS services
+that will likely be included in the kernel. And a draft of what
+functions each could or would include. Some functions also have
+a breif example of parameters required.
+
+Possible funture service groups or interfaces that could be system
+default include:
+- network functionality
+- general PCI devices
+- special one for all things USB?
+- GUI specific functions
+- running stuff in 16 and 64 bit, with extra DOS emulation
+ and/or other services
+
+
+
+
+services.asm (main service 0x00)
+--------------------------------------
+ always present in BOS, kernel
+--------------------------------------
+ - add service
+ signature dd 'VFS ', 'IO ', 'SND ', 'PCI '
+ version db 1
+ requested_no db 23 ; 0xFF or 0x00 to get assigned
+ service_struct dd 0 ; memory address of service calltable
+ - get servide
+ AL = number
+ returns all info above if service found
+ - remove service
+ AL = number
+ removes / unloads a service/interface
+ - get free number
+ AL = free service number ; always above 0x0F (below reserved)
+ - get BOS version (and other misc. kernel functions below)
+ - get/set interrupts
+ - execute kernel monitor command/script
+ - get time/date
+ - DMA functions, here or in VFS/floppy/memory drivers?
+ - GDT function, create new segments 'n shit
+ - pc-speaker beep if not even stdio is found
+ - CMOS / PIC functions
+ - run 16/64 bit code - seperate services for this? (int21h included?)
+ - get specified...
+
+
+stdio.asm (service number 0x01)
+--------------------------------------
+ needs to init itself as a service,
+ requesting servicenumber 1.
+ internal struct with info on
+ default in and out devices.
+--------------------------------------
+ - add device
+ type db 1 ; 0 = output, 1 = input
+ signature dd 'COM ', 'VGA ', 'VESA', 'FILE', 'NET ', 'USB ', 'KEYB', 'MICE'
+ version db 1
+ device_struct dd 0 ; address of calltable
+ - get device
+ AL = assigned device type ID / 0 for default?
+ returns all info above
+ - remove device
+ AL = assigned device type ID
+ removes device
+ - set default
+ AL = assigned device type ID
+ AH = 1 for in, 0 for out
+ - getc
+ get a char from stdin or specified device
+ - putc
+ put a char to stdout or specified device
+
+ .... other default stubs needed for STDIO ....
+
+
+vfs.asm (service number 0x02)
+--------------------------------------
+ needs to init itself as a service,
+ requesting servicenumber 2.
+ internal struct with info on
+ devices and filesystems.
+ add simple 'FILE' STDIO interface?
+--------------------------------------
+ - add device
+ - remove device
+ - get devices (list or number specified)
+ - read sector
+ - write sector
+ - seek
+ - more device specific stubs?
+ ...
+ - add fs
+ - remove fs
+ - parse path
+ - load file
+ - write file
+ - seek file
+ - close file
+ - mount device (with auto detect fs option)
+ - format fs (take device argument)
+ - more fs specific stubs?
+
+
+proccess.asm (service number 0x03)
+--------------------------------------
+ needs to init itself as a service,
+ requesting servicenumber 3.
+ possible to extend/replace for
+ multitasking.
+--------------------------------------
+ - Load process
+ needs VFS info to load file
+ - Exit process
+ - Terminate and Stay Resident
+ - Add exec. driver
+ interface to load driver/extensions for
+ more executable formats, possibly other
+ execution modes: realmode, longmode
+ - Remove driver
+
+
+memory.asm (service number 0x04)
+--------------------------------------
+ needs to init itself as a service,
+ requesting servicenumber 4.
+--------------------------------------
+ - lowalloc ? (for low mem, DMA & 16bit code)
+ - alloc
+ - realloc
+ - free
+ - DMA functions here? Possibly most related to mem?
\ No newline at end of file
;----------------;\r
; variables ;\r
;----------------;\r
- first_free dd 0\r
- prev_pointer dd 0\r
- size dd 0\r
- next_pointer dd 0\r
+ first_free dd 0\r
+ prev_pointer dd 0\r
+ size dd 0\r
+ next_pointer dd 0\r
\r
\r
;------------------------------------------------------;\r
; ecx = total memory size ;\r
;------------------------------------------------------;\r
init_mem:\r
- push ecx\r
+ push ecx\r
\r
- mov [first_free], ebx\r
- sub ecx, ebx\r
- mov [size], ecx\r
- mov [prev_pointer], 0\r
- mov [next_pointer], 0\r
- mov ecx, [prev_pointer]\r
- mov [ebx], ecx\r
- mov ecx, [size]\r
- mov [ebx+4], ecx\r
- mov ecx, [next_pointer]\r
- mov [ebx+8], ecx\r
+ mov [first_free], ebx\r
+ sub ecx, ebx\r
+ mov [size], ecx\r
+ mov [prev_pointer], 0\r
+ mov [next_pointer], 0\r
+ mov ecx, [prev_pointer]\r
+ mov [ebx], ecx\r
+ mov ecx, [size]\r
+ mov [ebx+4], ecx\r
+ mov ecx, [next_pointer]\r
+ mov [ebx+8], ecx\r
\r
- pop ecx\r
- ret\r
+ pop ecx\r
+ ret\r
\r
\r
\r
; ebx = pointer to memory ;\r
;------------------------------------------------------;\r
allocate_mem:\r
- push ecx\r
- push edx\r
-\r
- mov eax, [first_free]\r
-\r
- .loop:\r
- mov ecx, [eax]\r
- mov [prev_pointer], ecx\r
-\r
- mov ecx, [eax+4]\r
- mov [size], ecx\r
-\r
- mov ecx, [eax+8]\r
- mov [next_pointer], ecx\r
-\r
- cmp [size], ebx\r
- jae .found\r
- cmp [next_pointer], 0\r
- je .error\r
- mov eax, [next_pointer]\r
- jmp .loop\r
-\r
- .error:\r
- xor eax, eax\r
- jmp .end\r
-\r
- .found:\r
- mov ecx, [size]\r
- sub ecx, ebx\r
- jz .equal\r
-\r
- cmp [next_pointer], 0\r
- jne .next_exists\r
- cmp [prev_pointer], 0\r
- jne .prev_but_no_next\r
-\r
-\r
- ;----------------------------------------------;\r
- ; no other block exists; add new free block ;\r
- ; with the reminding space as free, and move ;\r
- ; "first free" to that block.. ;\r
- ;----------------------------------------------;\r
- mov ecx, eax ; move address to ecx and\r
- add ecx, ebx ; add size. ecx=end requested\r
- mov dword [ecx], 0 ; set new header's prev to 0\r
- mov edx, [size]\r
- sub edx, ebx ; remaining space in edx\r
- mov [ecx+4], edx ; save it to new header\r
- mov dword [ecx+8], 0 ; no next pointer..\r
-\r
- mov [first_free], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
- ;----------------------------------------------;\r
- ; no next block exists, make a new header at ;\r
- ; the end of the requested size with the ;\r
- ; reminder of the free space, and update the ;\r
- ; prev header's next pointer.. ;\r
- ;----------------------------------------------;\r
- .prev_but_no_next:\r
- mov ecx, eax ; move address to ecx and\r
- add ecx, ebx ; add size. ecx=end requested\r
- mov edx, [prev_pointer] ; set prev for new header\r
- mov [ecx], edx ; set new header's prev to 0\r
- mov edx, [size]\r
- sub edx, ebx ; remaining space in edx\r
- mov [ecx+4], edx ; save it to new header\r
- mov dword [ecx+8], 0 ; no next pointer..\r
-\r
- mov [prev_pointer+8], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
-\r
- ;----------------------------------------------;\r
- ; both next and previous blocks exists, make a ;\r
- ; new header at the end of the requested size ;\r
- ; with the reminder of the free space, move ;\r
- ; data from next block to the new one but add ;\r
- ; size so it gets right, then update all prev/ ;\r
- ; next pointers for total 3 blocks.. puh.. ;\r
- ;----------------------------------------------;\r
- .next_exists:\r
- cmp [prev_pointer], 0\r
- je .next_but_no_prev\r
-\r
- mov ecx, eax ; move address to ecx and\r
- add ecx, ebx ; add size. ecx=end requested\r
- mov edx, [prev_pointer] ; set prev for new header\r
- mov [ecx], edx ; set new header's prev\r
- mov edx, [size]\r
- sub edx, ebx\r
- mov ebx, [next_pointer+4]\r
- add edx, ebx ; remaining space in edx\r
- mov [ecx+4], edx ; save it to new header\r
- mov edx, [next_pointer] ; address to next block\r
- cmp dword [edx], 0\r
- je .no_next_next\r
- mov dword [edx], ecx ; update next-next's prev..\r
- mov dword [ecx+8], edx ; address to next pointer.\r
-\r
- mov [prev_pointer+8], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
- .no_next_next:\r
- mov dword [edx], 0\r
- mov dword [ecx+8], 0\r
- mov [prev_pointer+8], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
-\r
- ;----------------------------------------------;\r
- ; we allocated the first free block, do the ;\r
- ; same as above, except ignore the prev block ;\r
- ; part, and move the "first free". ;\r
- ;----------------------------------------------;\r
- .next_but_no_prev:\r
- mov ecx, eax ; move address to ecx and\r
- add ecx, ebx ; add size. ecx=end requested\r
- mov dword [ecx], 0 ; set new header's prev to 0\r
- mov edx, [size]\r
- sub edx, ebx\r
- mov ebx, [next_pointer+4]\r
- add edx, ebx ; remaining space in edx\r
- mov [ecx+4], edx ; save it to new header\r
- mov edx, [next_pointer] ; address to next block\r
- cmp dword [edx], 0\r
- je .no_next_next2\r
- mov dword [edx], ecx ; update next-next's prev..\r
- mov dword [ecx+8], edx ; address to next pointer.\r
-\r
- mov [first_free], ecx ; zero and update first free.\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
- .no_next_next2:\r
- mov dword [edx], 0\r
- mov ecx, [ecx+8]\r
- mov dword [ecx], 0\r
- mov [prev_pointer+8], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
-\r
- ;-----------------------------------------;\r
- ; requested == size ;\r
- ; I prefered coding this one.. ;) ;\r
- ;-----------------------------------------;\r
- .equal:\r
- cmp [next_pointer], 0\r
- jne .next_exists2\r
- cmp [prev_pointer], 0\r
- jne .prev_but_no_next2\r
- mov [first_free], 0\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
- .prev_but_no_next2:\r
- mov dword [prev_pointer+8], 0\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
- .next_exists2:\r
- cmp [prev_pointer], 0\r
- je .next_but_no_prev2\r
- mov ecx, [prev_pointer] ; update prev and next's\r
- mov edx, [next_pointer] ; headers to bypass this\r
- mov [ecx+8], edx ; chunk.\r
- mov [edx], ecx\r
- mov ebx, eax ; eax is unchanged from loop\r
- jmp .end\r
-\r
- .next_but_no_prev2:\r
- mov ecx, [eax+8] ; get address of next header\r
- mov dword [ecx], 0 ; set prev in next header to\r
- mov [first_free], ecx ; zero and update first free.\r
- mov ebx, eax ; eax is unchanged from loop\r
-\r
- .end:\r
- pop edx\r
- pop ecx\r
- ret\r
+ push ecx\r
+ push edx\r
+\r
+ mov eax, [first_free]\r
+\r
+ .loop:\r
+ mov ecx, [eax]\r
+ mov [prev_pointer], ecx\r
+\r
+ mov ecx, [eax+4]\r
+ mov [size], ecx\r
+\r
+ mov ecx, [eax+8]\r
+ mov [next_pointer], ecx\r
+\r
+ cmp [size], ebx\r
+ jae .found\r
+ cmp [next_pointer], 0\r
+ je .error\r
+ mov eax, [next_pointer]\r
+ jmp .loop\r
+\r
+ .error:\r
+ xor eax, eax\r
+ jmp .end\r
+\r
+ .found:\r
+ mov ecx, [size]\r
+ sub ecx, ebx\r
+ jz .equal\r
+\r
+ cmp [next_pointer], 0\r
+ jne .next_exists\r
+ cmp [prev_pointer], 0\r
+ jne .prev_but_no_next\r
+\r
+\r
+ ;----------------------------------------------;\r
+ ; no other block exists; add new free block ;\r
+ ; with the reminding space as free, and move ;\r
+ ; "first free" to that block.. ;\r
+ ;----------------------------------------------;\r
+ mov ecx, eax ; move address to ecx and\r
+ add ecx, ebx ; add size. ecx=end requested\r
+ mov dword [ecx], 0 ; set new header's prev to 0\r
+ mov edx, [size]\r
+ sub edx, ebx ; remaining space in edx\r
+ mov [ecx+4], edx ; save it to new header\r
+ mov dword [ecx+8], 0 ; no next pointer..\r
+\r
+ mov [first_free], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+ ;----------------------------------------------;\r
+ ; no next block exists, make a new header at ;\r
+ ; the end of the requested size with the ;\r
+ ; reminder of the free space, and update the ;\r
+ ; prev header's next pointer.. ;\r
+ ;----------------------------------------------;\r
+ .prev_but_no_next:\r
+ mov ecx, eax ; move address to ecx and\r
+ add ecx, ebx ; add size. ecx=end requested\r
+ mov edx, [prev_pointer] ; set prev for new header\r
+ mov [ecx], edx ; set new header's prev to 0\r
+ mov edx, [size]\r
+ sub edx, ebx ; remaining space in edx\r
+ mov [ecx+4], edx ; save it to new header\r
+ mov dword [ecx+8], 0 ; no next pointer..\r
+\r
+ mov [prev_pointer+8], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+\r
+ ;----------------------------------------------;\r
+ ; both next and previous blocks exists, make a ;\r
+ ; new header at the end of the requested size ;\r
+ ; with the reminder of the free space, move ;\r
+ ; data from next block to the new one but add ;\r
+ ; size so it gets right, then update all prev/ ;\r
+ ; next pointers for total 3 blocks.. puh.. ;\r
+ ;----------------------------------------------;\r
+ .next_exists:\r
+ cmp [prev_pointer], 0\r
+ je .next_but_no_prev\r
+\r
+ mov ecx, eax ; move address to ecx and\r
+ add ecx, ebx ; add size. ecx=end requested\r
+ mov edx, [prev_pointer] ; set prev for new header\r
+ mov [ecx], edx ; set new header's prev\r
+ mov edx, [size]\r
+ sub edx, ebx\r
+ mov ebx, [next_pointer+4]\r
+ add edx, ebx ; remaining space in edx\r
+ mov [ecx+4], edx ; save it to new header\r
+ mov edx, [next_pointer] ; address to next block\r
+ cmp dword [edx], 0\r
+ je .no_next_next\r
+ mov dword [edx], ecx ; update next-next's prev..\r
+ mov dword [ecx+8], edx ; address to next pointer.\r
+\r
+ mov [prev_pointer+8], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+ .no_next_next:\r
+ mov dword [edx], 0\r
+ mov dword [ecx+8], 0\r
+ mov [prev_pointer+8], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+\r
+ ;----------------------------------------------;\r
+ ; we allocated the first free block, do the ;\r
+ ; same as above, except ignore the prev block ;\r
+ ; part, and move the "first free". ;\r
+ ;----------------------------------------------;\r
+ .next_but_no_prev:\r
+ mov ecx, eax ; move address to ecx and\r
+ add ecx, ebx ; add size. ecx=end requested\r
+ mov dword [ecx], 0 ; set new header's prev to 0\r
+ mov edx, [size]\r
+ sub edx, ebx\r
+ mov ebx, [next_pointer+4]\r
+ add edx, ebx ; remaining space in edx\r
+ mov [ecx+4], edx ; save it to new header\r
+ mov edx, [next_pointer] ; address to next block\r
+ cmp dword [edx], 0\r
+ je .no_next_next2\r
+ mov dword [edx], ecx ; update next-next's prev..\r
+ mov dword [ecx+8], edx ; address to next pointer.\r
+\r
+ mov [first_free], ecx ; zero and update first free.\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+ .no_next_next2:\r
+ mov dword [edx], 0\r
+ mov ecx, [ecx+8]\r
+ mov dword [ecx], 0\r
+ mov [prev_pointer+8], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+\r
+ ;-----------------------------------------;\r
+ ; requested == size ;\r
+ ; I prefered coding this one.. ;) ;\r
+ ;-----------------------------------------;\r
+ .equal:\r
+ cmp [next_pointer], 0\r
+ jne .next_exists2\r
+ cmp [prev_pointer], 0\r
+ jne .prev_but_no_next2\r
+ mov [first_free], 0\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+ .prev_but_no_next2:\r
+ mov dword [prev_pointer+8], 0\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+ .next_exists2:\r
+ cmp [prev_pointer], 0\r
+ je .next_but_no_prev2\r
+ mov ecx, [prev_pointer] ; update prev and next's\r
+ mov edx, [next_pointer] ; headers to bypass this\r
+ mov [ecx+8], edx ; chunk.\r
+ mov [edx], ecx\r
+ mov ebx, eax ; eax is unchanged from loop\r
+ jmp .end\r
+\r
+ .next_but_no_prev2:\r
+ mov ecx, [eax+8] ; get address of next header\r
+ mov dword [ecx], 0 ; set prev in next header to\r
+ mov [first_free], ecx ; zero and update first free.\r
+ mov ebx, eax ; eax is unchanged from loop\r
+\r
+ .end:\r
+ pop edx\r
+ pop ecx\r
+ ret\r
\r
\r
\r
; ecx = size in bytes ;\r
;------------------------------------------------------;\r
free_mem:\r
- push eax\r
- push ebx\r
- push ecx\r
- push edx\r
-\r
- cmp ebx, [first_free]\r
- jb .new_first_free\r
- cmp [first_free], 0\r
- je .new_first_free\r
-\r
- ;-----------------------------------------------------------;\r
- ; the block we want to free is somewhere in between ;\r
- ; two other free blocks or after the last free block. ;\r
- ; search for the "ebx"-address, so we know where the new ;\r
- ; prev/next pointers are, and then can check if we should ;\r
- ; merge blocks.. ;\r
- ;-----------------------------------------------------------;\r
- mov eax, [first_free] ; "current" free block\r
- mov edx, [eax+8] ; next free block\r
-\r
- .find_pos_loop:\r
- cmp edx, 0 ; check if the "next"\r
- je .found_end_of_ram ; free exists..\r
-\r
- cmp ebx, edx ; is ebx "below" edx?\r
- jb .found_between ; found ebx in between\r
-\r
- mov eax, edx ; update pointers for\r
- mov edx, [eax+8] ; another loop.\r
- jmp .find_pos_loop\r
-\r
- ;------------------------------------------;\r
- ; the block is between two other blocks ;\r
- ;------------------------------------------;\r
- .found_between:\r
- mov [ebx], eax ; create header\r
- mov [ebx+4], ecx\r
- mov [ebx+8], edx\r
-\r
- mov [eax+8], ebx ; update prev header\r
- mov [edx], ebx ; update next header\r
-\r
- ; now check if we can merge blocks....\r
- add ecx, ebx\r
- cmp edx, ecx\r
- jne .merge_only_first\r
- push eax\r
- add eax, [eax+4]\r
- cmp ebx, eax\r
- pop eax\r
- jne .merge_only_last\r
-\r
- ; we can merge with both prev & next\r
- mov ecx, [ebx+4] ; get size from "current"\r
- add [eax+4], ecx ; and add it to "prev".\r
- mov ecx, [edx+4] ; get size from "next"\r
- add [eax+4], ecx ; and add it to "prev".\r
- mov ecx, [edx+8] ; get the new next\r
- mov [eax+8], ecx ; pointer, and store it.\r
- cmp ecx, 0\r
- je .end\r
- mov [ecx], eax\r
- jmp .end\r
-\r
- .merge_only_first:\r
- cmp ebx, eax\r
- jne .end\r
- mov ecx, [ebx+4] ; get size from "current"\r
- add [eax+4], ecx ; and add it to "prev".\r
- mov [edx], eax ; update prev and next\r
- mov [eax+8], edx ; pointers for the two..\r
- jmp .end\r
-\r
- .merge_only_last:\r
- cmp edx, ecx\r
- jne .end\r
- mov ecx, [edx+4]\r
- add [ebx+4], ecx\r
- mov ecx, [edx+8]\r
- mov [ebx+8], ecx\r
- cmp ecx, 0\r
- je .end\r
- mov [ecx], ebx\r
- jmp .end\r
-\r
- ;----------------------------------------------;\r
- ; the block is after all existing free ones ;\r
- ;----------------------------------------------;\r
- .found_end_of_ram:\r
- mov [ebx], eax ; create header\r
- mov [ebx+4], ecx\r
- mov [ebx+8], edx\r
-\r
- mov [eax+8], ebx ; update prev header\r
-\r
- ; now check if we can merge the blocks....\r
- mov ecx, eax\r
- add ecx, [eax+4]\r
- cmp ebx, ecx\r
- jne .end\r
- mov ecx, [ebx+4]\r
- add [eax+4], ecx\r
- mov ecx, [ebx+8]\r
- mov [eax+8], ecx\r
- jmp .end\r
-\r
- ;--------------------------------------------;\r
- ; the block is before any other free ones ;\r
- ;--------------------------------------------;\r
- .new_first_free:\r
- mov dword [ebx], 0\r
- mov [ebx+4], ecx ; create the\r
- mov edx, [first_free] ; new header\r
- mov [ebx+8], edx\r
-\r
- mov edx, ebx ; check if the\r
- add edx, [ebx+4] ; first_free matches\r
- cmp edx, [first_free] ; current pos + size?\r
- je .merge_first_free ; if so, merge the two\r
-\r
- cmp [first_free], 0 ; else check if\r
- je .cont1 ; first_free exists\r
- mov edx, [ebx+8] ; if it does, update\r
- mov [edx], ebx ; it's prev pointer.\r
- .cont1:\r
- mov [first_free], ebx ; else/and set new\r
- jmp .end ; first free and quit\r
-\r
- .merge_first_free: ; merge the two first\r
- mov edx, [ebx+8] ; add the size of the\r
- mov ecx, [edx+4] ; second block to the\r
- add [ebx+4], ecx ; new one.\r
- mov ecx, [edx+8] ; get the next pointer\r
- mov [ebx+8], ecx ; from the old block,\r
- cmp ecx, 0\r
- je .cont2\r
- mov [ecx], ebx ; update this + next..\r
- .cont2:\r
- mov [first_free], ebx ; update first_free\r
-\r
- .end:\r
- pop edx\r
- pop ecx\r
- pop ebx\r
- pop eax\r
- ret
\ No newline at end of file
+ push eax\r
+ push ebx\r
+ push ecx\r
+ push edx\r
+\r
+ cmp ebx, [first_free]\r
+ jb .new_first_free\r
+ cmp [first_free], 0\r
+ je .new_first_free\r
+\r
+ ;-----------------------------------------------------------;\r
+ ; the block we want to free is somewhere in between ;\r
+ ; two other free blocks or after the last free block. ;\r
+ ; search for the "ebx"-address, so we know where the new ;\r
+ ; prev/next pointers are, and then can check if we should ;\r
+ ; merge blocks.. ;\r
+ ;-----------------------------------------------------------;\r
+ mov eax, [first_free] ; "current" free block\r
+ mov edx, [eax+8] ; next free block\r
+\r
+ .find_pos_loop:\r
+ cmp edx, 0 ; check if the "next"\r
+ je .found_end_of_ram ; free exists..\r
+\r
+ cmp ebx, edx ; is ebx "below" edx?\r
+ jb .found_between ; found ebx in between\r
+\r
+ mov eax, edx ; update pointers for\r
+ mov edx, [eax+8] ; another loop.\r
+ jmp .find_pos_loop\r
+\r
+ ;------------------------------------------;\r
+ ; the block is between two other blocks ;\r
+ ;------------------------------------------;\r
+ .found_between:\r
+ mov [ebx], eax ; create header\r
+ mov [ebx+4], ecx\r
+ mov [ebx+8], edx\r
+\r
+ mov [eax+8], ebx ; update prev header\r
+ mov [edx], ebx ; update next header\r
+\r
+ ; now check if we can merge blocks....\r
+ add ecx, ebx\r
+ cmp edx, ecx\r
+ jne .merge_only_first\r
+ push eax\r
+ add eax, [eax+4]\r
+ cmp ebx, eax\r
+ pop eax\r
+ jne .merge_only_last\r
+\r
+ ; we can merge with both prev & next\r
+ mov ecx, [ebx+4] ; get size from "current"\r
+ add [eax+4], ecx ; and add it to "prev".\r
+ mov ecx, [edx+4] ; get size from "next"\r
+ add [eax+4], ecx ; and add it to "prev".\r
+ mov ecx, [edx+8] ; get the new next\r
+ mov [eax+8], ecx ; pointer, and store it.\r
+ cmp ecx, 0\r
+ je .end\r
+ mov [ecx], eax\r
+ jmp .end\r
+\r
+ .merge_only_first:\r
+ cmp ebx, eax\r
+ jne .end\r
+ mov ecx, [ebx+4] ; get size from "current"\r
+ add [eax+4], ecx ; and add it to "prev".\r
+ mov [edx], eax ; update prev and next\r
+ mov [eax+8], edx ; pointers for the two..\r
+ jmp .end\r
+\r
+ .merge_only_last:\r
+ cmp edx, ecx\r
+ jne .end\r
+ mov ecx, [edx+4]\r
+ add [ebx+4], ecx\r
+ mov ecx, [edx+8]\r
+ mov [ebx+8], ecx\r
+ cmp ecx, 0\r
+ je .end\r
+ mov [ecx], ebx\r
+ jmp .end\r
+\r
+ ;----------------------------------------------;\r
+ ; the block is after all existing free ones ;\r
+ ;----------------------------------------------;\r
+ .found_end_of_ram:\r
+ mov [ebx], eax ; create header\r
+ mov [ebx+4], ecx\r
+ mov [ebx+8], edx\r
+\r
+ mov [eax+8], ebx ; update prev header\r
+\r
+ ; now check if we can merge the blocks....\r
+ mov ecx, eax\r
+ add ecx, [eax+4]\r
+ cmp ebx, ecx\r
+ jne .end\r
+ mov ecx, [ebx+4]\r
+ add [eax+4], ecx\r
+ mov ecx, [ebx+8]\r
+ mov [eax+8], ecx\r
+ jmp .end\r
+\r
+ ;--------------------------------------------;\r
+ ; the block is before any other free ones ;\r
+ ;--------------------------------------------;\r
+ .new_first_free:\r
+ mov dword [ebx], 0\r
+ mov [ebx+4], ecx ; create the\r
+ mov edx, [first_free] ; new header\r
+ mov [ebx+8], edx\r
+\r
+ mov edx, ebx ; check if the\r
+ add edx, [ebx+4] ; first_free matches\r
+ cmp edx, [first_free] ; current pos + size?\r
+ je .merge_first_free ; if so, merge the two\r
+\r
+ cmp [first_free], 0 ; else check if\r
+ je .cont1 ; first_free exists\r
+ mov edx, [ebx+8] ; if it does, update\r
+ mov [edx], ebx ; it's prev pointer.\r
+ .cont1:\r
+ mov [first_free], ebx ; else/and set new\r
+ jmp .end ; first free and quit\r
+\r
+ .merge_first_free: ; merge the two first\r
+ mov edx, [ebx+8] ; add the size of the\r
+ mov ecx, [edx+4] ; second block to the\r
+ add [ebx+4], ecx ; new one.\r
+ mov ecx, [edx+8] ; get the next pointer\r
+ mov [ebx+8], ecx ; from the old block,\r
+ cmp ecx, 0\r
+ je .cont2\r
+ mov [ecx], ebx ; update this + next..\r
+ .cont2:\r
+ mov [first_free], ebx ; update first_free\r
+\r
+ .end:\r
+ pop edx\r
+ pop ecx\r
+ pop ebx\r
+ pop eax\r
+ ret
\ No newline at end of file