; ES = Object table segment ; CX = Object count, must be divisible by 8 TABLE_InitializeBitmap: MOV WORD [ES:0], CX ; Store the object count SHR CX, 3 ; Divide CX by 8 MOV AL, 0 ; Fill with zeroes XOR DI, DI ; The bitmap is the first section of the table save for the obj count ADD DI, 2 ; First WORD is the object count REP STOSB ; TIMES CX Fill ES:DI with AL. ; We can't assume the bitmap will be divisible by a WORD or DWORD, ; but thankfully this only really gets called once during the entire lifetime of the program. RET ; ES = Object table segment ; AX = Object handle ; RET: ES:DI = Object addr TABLE_GetObjectAddr: MOV WORD BX, [ES:0] ; Get object count MOV DI, BX ; Set to object count SHR DI, 3 ; Divide by 8 ADD DI, 2 ; And skip the object count ADD DI, BX ; Then add object lengths SHL AX, 4 ; Multiply the object handle by 16 ADD DI, AX ; And point to the proper paragraph ADD DI, 15 ; Make sure we round up if not aligned AND DI, 0xFFF0 ; Clear the lower 4 bits to align to 16 bytes RET ; AX = Object handle ; ES = Object table segment TABLE_ObjFree: PUSH DI ; Store DI MOV DI, [ES:0] ; Store object count SHR DI, 3 ; Divide by 8 to skip the bitmap ADD DI, 2 ; Skip the object count WORD ADD DI, AX ; Ptr to the object length MOV BYTE CL, [ES:DI] ; Get the object length CALL TABLE_INTR_ObjFree ; And free the specified bits POP DI ; Restore DI RET ; ES = Object table segment ; AX = Object handle ; CX = Number of paragraphs to free TABLE_INTR_ObjFree: PUSH AX ; Store the object handle PUSH CX ; And store the object length .loop: BTR [ES:2], AX ; Object handle is simply the object position, we can use it verbatim INC AX ; Increase the bit position DEC CX ; And decrease the counter JNZ .loop ; If counter is nonzero, loop POP CX ; Restore object length POP AX ; Restore object handle ; Technically those two are now invalid, but I'm not sure how the final code will look like. RET ; ES = Object segment ; DX = Object offset ; CX = Object length TABLE_INTR_SetObjLength: PUSH DI ; Store DI MOV WORD DI, [ES:0] ; Store the object count SHR DI, 3 ; Divide by 8 to skip the bitmap ADD DI, 2 ; Skip the object count ADD DI, DX ; Ptr to the object size MOV BYTE [ES:DI], CL ; Store the object size POP DI ; And restore DI RET ; ES = Object table segment ; CX = Number of paragraphs to allocate ; RET AX = Object handle (bit index) TABLE_ObjAlloc: PUSH CX MOV BX, [ES:0] ; Object count SUB BX, CX ; Max starting bit index = total - needed XOR DX, DX ; DX = current bit index (our cursor) .next_candidate: PUSH DX ; Save starting bit index PUSH CX ; Save number of bits to test MOV SI, DX ; SI = test index MOV DI, CX ; DI = countdown .test_bits: BT [ES:2], SI JC .bit_used ; If bit set, abort this sequence INC SI DEC DI JNZ .test_bits ; If we got here, we found CX contiguous 0s starting at DX POP CX ; Restore CX for writing POP DX ; DX = starting index MOV SI, DX .set_bits: BTS [ES:2], SI INC SI LOOP .set_bits MOV AX, DX ; Return object handle = starting bit POP CX ; Clean up CALL TABLE_INTR_SetObjLength RET .bit_used: POP CX POP DX INC DX CMP DX, BX JBE .next_candidate .fail: MOV AX, 0xFFFF ; Error: no space STC RET