; ============================================================================= ; ; Litos8 memory manager ; ; ============================================================================= ; Memory manager uses 1KB pages. There are 64 of 1KB pages total. Each page ; can be divided into small memory segment of size 8, 16, 32, 64, 128, 256, ; or 512 bytes. There can be only segment of the same size, in one page. ; Each size of small memory blocks (i.e. 8..512) has its own bit table of used ; memory segments. Bit table of 8 byte blocks has size: 10000h/8/8=1024 bytes, ; bit table of 16 byte: 512 bytes, etc. ; ----------------------------------------------------------------------------- ; Exported user functions (9): ; MemAlloc - allocate memory block ; MemFree - free memory block ; MemResize - resize memory block ; MemDup - duplicate memory block ; MemGetSize - get memory block size, check block address validity ; MemMaxFree - get maximum available memory block ; MemGetFreeTotal - get total free memory ; MemGetUsedTotal - get total used memory ; GetSysMemSize - get size of system memory ; ----------------------------------------------------------------------------- PAGE_SIZE EQU 1024 ; size of memory page PAGE_MASK EQU PAGE_SIZE-1 ; page mask PAGE_BITS EQU 10 ; number of bits per memory page PAGE_NUM EQU 64 ; total number of pages MEM_SIZE_FREE EQU 0 ; page is free MEM_SIZE8 EQU 1 ; block size 8 bytes MEM_SIZE16 EQU 2 ; block size 16 bytes MEM_SIZE32 EQU 3 ; block size 32 bytes MEM_SIZE64 EQU 4 ; block size 64 bytes MEM_SIZE128 EQU 5 ; block size 128 bytes MEM_SIZE256 EQU 6 ; block size 256 bytes MEM_SIZE512 EQU 7 ; block size 512 bytes MEM_SIZEKB EQU 8 ; block size xKB (number_of_KB + 7) MEM_SIZE_USED EQU 255 ; flag - used block of xKB block string MEM_KB_BIAS EQU 7 ; bias of block size in KB CODE_SECTION ; ----------------------------------------------------------------------------- ; Initialize memory manager ; ----------------------------------------------------------------------------- ; NOTES: Should be called before loading user program. ; ----------------------------------------------------------------------------- ; ------------- push registers MemInit: push ax ; push AX push bx ; push BX push cx ; push CX push di ; push DI ; ------------- initialize memory statistic xor ax,ax ; AX <- 0 mov word [MemFreeTotal],ax ; total free memory = 64 KB mov word [MemUsedTotal],ax ; total used memory = 0 ; ------------- clear tables (here AX = 0) mov di,TablesStart ; DI <- tables mov cx,(TablesEnd-TablesStart)/2 ; CX <- size of tables rep stosw ; clear table ; ------------- allocate reserved memory 0...0fffh (4 KB) xor bx,bx ; BX <- reserved start address mov al,MEM_KB_BIAS+4 ; AL <- block size, 4 KB call MemMark ; mark block of memory ; ------------- allocate kernel memory mov bx,KernelStart ; BX <- kernel start address and bx,~PAGE_MASK ; round kernel start down mov ax,KernelEnd ; AX <- kernel end address add ax,PAGE_SIZE-1 ; round kernel end up and ax,~PAGE_MASK ; mask kernel end address sub ax,bx ; AX <- kernel size mov cl,PAGE_BITS ; CL <- number of bits per page shr ax,cl ; AX <- number of pages add al,MEM_KB_BIAS ; AL <- block size call MemMark ; mark block of memory ; ------------- pop registers pop di ; pop DI pop cx ; pop CX pop bx ; pop BX pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Get total free memory ; ----------------------------------------------------------------------------- ; OUTPUT: AX = total free memory (in bytes) ; ----------------------------------------------------------------------------- MemGetFreeTotal:mov ax,[MemFreeTotal] ret ; ----------------------------------------------------------------------------- ; Get total used memory ; ----------------------------------------------------------------------------- ; OUTPUT: AX = total used memory (in bytes) ; ----------------------------------------------------------------------------- MemGetUsedTotal:mov ax,[MemUsedTotal] ret ; ----------------------------------------------------------------------------- ; Get size of system memory (640 KB) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = size of system memory (in KB) ; ----------------------------------------------------------------------------- GetSysMemSize: mov ax,[MemSizeKB] ret ; ----------------------------------------------------------------------------- ; Mark single block as used ; ----------------------------------------------------------------------------- ; INPUT: AL = block size (MEM_SIZE8,...) ; BX = block address ; ----------------------------------------------------------------------------- ; ------------- push registers MemMark: push ax ; push AX push cx ; push CX push dx ; push DX push di ; push DI ; ------------- set size of first block mov ah,0 ; AX = block size mov di,bx ; DI <- block address mov cl,PAGE_BITS ; CL <- 10, size of 1 KB block shr di,cl ; DI <- offset of descriptor add di,MemSizeTab ; DI <- descriptor address inc byte [di-MemSizeTab+MemUsedTab] ; used counter stosb ; set first block ; ------------- mark small block mov ch,1 ; CH <- 1, only 1 block cmp al,MEM_SIZEKB ; big block? jb short MemMark6 ; small block ; ------------- set block size of big block mov cx,ax ; CX <- block size sub cl,MEM_KB_BIAS+1 ; CL <- number of 1 KB blocks - 1 jz short MemMark4 ; no other blocks MemMark2: inc byte [di-MemSizeTab+MemUsedTab] ; used counter mov byte [di],MEM_SIZE_USED ; initialize other descriptors inc di ; DI <- next block loop MemMark2 ; next block ; ------------- mark bits of used KB blocks MemMark4: sub al,MEM_KB_BIAS ; AX <- number of 1 KB blocks mov ch,al ; CH <- number of 1 KB blocks mov al,MEM_SIZEKB ; AL <- 1KB block ; ------------- prepare address of bitmap table -> DI MemMark6: mov di,ax ; DI <- block size shl di,1 ; DI <- offset of table mov di,[di+MemBitMapAddr-2] ; DI <- address of table ; ------------- address in bitmap table -> DI mov cl,al ; AL <- block size add cl,2+3 ; CL <- 2 for size, 3 for bit mov ax,bx ; AX <- block address shr ax,cl ; AX <- offset it bitmap table add di,ax ; DI <- address in bitmap table ; ------------- bit mask -> AL, block size -> DX mov ax,bx ; AX <- address sub cl,3 ; CL <- bits per block xor dx,dx ; DX <- 0 shr ax,cl ; AX <- number of block inc dx ; DX <- 1 and al,7 ; AL <- bit in byte shl dx,cl ; DX <- size of block mov cl,al ; CL <- bit in byte mov al,1 ; AL <- bit 0 shl al,cl ; AL <- bit mask ; ------------- mark blocks MemMark8: or byte [di],al ; set one bit sub [MemFreeTotal],dx ; total free memory add [MemUsedTotal],dx ; total used memory rol al,1 ; AL <- shift by one bit adc di,byte 0 ; DI <- shift address dec ch ; counter of blocks jnz short MemMark8 ; next block ; ------------- pop registers pop di ; pop DI pop dx ; pop DX pop cx ; pop CX pop ax ; pop AX MemMark9: ret ; ----------------------------------------------------------------------------- ; Get memory block size, check if memory block is valid ; ----------------------------------------------------------------------------- ; INPUT: AX = block address (can be NULL) ; OUTPUT: AX = block size (NC), or 0 if invalid memory block (CY) ; CY = invalid memory block (AX = 0) ; ----------------------------------------------------------------------------- ; ------------- check block address MemGetSize: or ax,ax ; is block valid? jz short MemGetSize8 ; block is NULL ; ------------- push registers push bx ; push BX push cx ; push CX push dx ; push DX ; ------------- kernel address is invalid cmp ax,KernelStart ; kernel address je short MemGetSize6 ; kernel address ; ------------- get block size module -> AL mov dx,ax ; DX <- save block address xchg ax,bx ; BX <- memory block address mov cl,PAGE_BITS ; CL <- 10, size of 1 KB block shr bx,cl ; BX <- offset of descriptor cmp byte [bx+MemUsedTab],0 ; check used table je short MemGetSize6 ; invalid memory block mov al,[bx+MemSizeTab] ; AL <- block size or al,al ; free memory block? jz short MemGetSize6 ; invalid memory block cmp al,MEM_SIZE_USED ; used block of xKB string? je short MemGetSize6 ; xKB string, invalid block address ; ------------- get small block size in bytes -> AX cmp al,MEM_SIZEKB ; small block? jae short MemGetSize2 ; big block mov bl,al ; BL <- block size module add al,2 ; AL <- number of bits mov cl,al ; CL <- number of bits xor ax,ax ; AX <- 0 inc ax ; AX <- 1 shl ax,cl ; AX <- block size ; ------------- check block address align dec ax ; AX <- block size - 1 test dx,ax ; check address align jnz short MemGetSize6 ; invalid memory block address inc ax ; AX <- block size jmp short MemGetSize4 ; ------------- block size in KB -> AX MemGetSize2: test dx,PAGE_MASK ; check address align jnz short MemGetSize6 ; invalid memory block address sub al,MEM_KB_BIAS ; AL <- number of KB mov ah,0 ; AX = number of KB shl ax,cl ; AX <- block size mov bl,MEM_SIZEKB ; BL <- block size module ; ------------- prepare address of bitmap table -> BX MemGetSize4: push ax ; push AX (block size) mov cl,bl ; CL <- block size module mov bh,0 ; BX = block size module shl bx,1 ; BX <- offset of table mov bx,[bx+MemBitMapAddr-2] ; BX <- address of table ; ------------- address in bitmap table -> BX add cl,2+3 ; CL <- 2 for size, 3 for bit mov ax,dx ; DX <- block address shr ax,cl ; DX <- offset it bitmap table add bx,ax ; BX <- address in bitmap table ; ------------- bit mask -> AL sub cl,3 ; CL <- bits per block shr dx,cl ; DX <- number of block and dl,7 ; DL <- bit in byte mov cl,dl ; CL <- bit in byte mov al,1 ; AL <- bit 0 shl al,cl ; AL <- bit mask ; ------------- test block test byte [bx],al ; text bit pop ax ; pop AX (block size) jnz short MemGetSize7 ; block is marked OK ; ------------- invalid memory block MemGetSize6: xor ax,ax ; AX <- invalid memory block ; ------------- pop registers MemGetSize7: pop dx ; pop DX pop cx ; pop CX pop bx ; pop BX MemGetSize8: cmp ax,1 ; check memory block size MemGetSize9: ret ; ----------------------------------------------------------------------------- ; Free memory block ; ----------------------------------------------------------------------------- ; INPUT: AX = block address (can be NULL) ; OUTPUT: AX = block address, or 0 (NULL) if invalid memory block (CY) ; CY = invalid memory block ; ----------------------------------------------------------------------------- ; ------------- check block address MemFree: push ax ; push AX call MemGetSize ; check memory block pop ax ; pop AX jnc short MemFreeNoCheck ; memory block is OK xor ax,ax ; AX <- 0, invalid memory block stc ; set error flag ret ; ------------- push registers MemFreeNoCheck: push ax ; push AX push bx ; push BX push cx ; push CX push dx ; push DX push di ; push DI ; ------------- get block size -> AL xchg ax,bx ; BX <- memory block address mov ah,1 ; AH <- flag, don't clear block mov di,bx ; DI <- block address mov cl,PAGE_BITS ; CL <- 10, size of 1 KB block shr di,cl ; DI <- offset of descriptor add di,MemSizeTab ; DI <- descriptor address mov al,[di] ; AL <- block size ; ------------- clear size of first block dec byte [di-MemSizeTab+MemUsedTab] ; used counter jnz short MemFree2 ; not last block mov ah,0 ; AH <- 0, clear block size mov [di],ah ; clear block size inc di ; DI <- next block ; ------------- mark small block MemFree2: mov ch,1 ; CH <- 1, only 1 block cmp al,MEM_SIZEKB ; big block? jb short MemFree6 ; small block ; ------------- set block size of big block or ah,ah ; clear block? jnz short MemFree4 ; don't clear block mov cx,ax ; CL <- block size sub cl,MEM_KB_BIAS+1 ; CL <- number of 1 KB blocks - 1 jz short MemFree4 ; no other blocks MemFree3: mov [di-MemSizeTab+MemUsedTab],ah ; clear used counter mov [di],ah ; clear block size inc di ; DI <- next block loop MemFree3 ; next block ; ------------- mark bits of used KB blocks MemFree4: sub al,MEM_KB_BIAS ; AX <- number of 1 KB blocks mov ch,al ; CH <- number of 1 KB blocks mov al,MEM_SIZEKB ; AL <- 1KB block ; ------------- prepare address of bitmap table -> DI MemFree6: mov ah,0 ; AX = block size mov di,ax ; DI <- block size shl di,1 ; DI <- offset of table mov di,[di+MemBitMapAddr-2] ; DI <- address of table ; ------------- address in bitmap table -> DI mov cl,al ; AL <- block size add cl,2+3 ; CL <- 2 for size, 3 for bit mov ax,bx ; AX <- block address shr ax,cl ; AX <- offset it bitmap table add di,ax ; DI <- address in bitmap table ; ------------- bit mask -> AL, block size -> DX mov ax,bx ; AX <- address sub cl,3 ; CL <- bits per block xor dx,dx ; DX <- 0 shr ax,cl ; AX <- number of block inc dx ; DX <- 1 and al,7 ; AL <- bit in byte shl dx,cl ; DX <- size of block mov cl,al ; CL <- bit in byte mov al,1 ; AL <- bit 0 shl al,cl ; AL <- bit mask ; ------------- unmark blocks MemFree8: xor byte [di],al ; clear one bit add [MemFreeTotal],dx ; total free memory sub [MemUsedTotal],dx ; total used memory rol al,1 ; AL <- shift by one bit adc di,byte 0 ; DI <- shift address dec ch ; counter of blocks jnz short MemFree8 ; next block ; ------------- pop registers pop di ; pop DI pop dx ; pop DX pop cx ; pop CX pop bx ; pop BX pop ax ; pop AX clc ; clear error flag ret ; ----------------------------------------------------------------------------- ; Get biggest free memory space that can be allocated (only xKB) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = max. size of free memory space ; ----------------------------------------------------------------------------- ; ------------- push registers MemMaxFree: push bx ; push BX push dx ; push DX ; ------------- prepare registers xor ax,ax ; AX <- 0, found biggest memory block xor bx,bx ; BX <- 0, offset in table xor dx,dx ; DX <- 0, size accumulator ; ------------- find free memory block MemMaxFree2: cmp byte [MemSizeTab+bx],0 ; free block? je short MemMaxFree4 ; free block cmp dx,ax ; block is bigger ? jb short MemMaxFree3 ; block is smaller xchg ax,dx ; AX <- found biggest block MemMaxFree3: mov dx,-PAGE_SIZE ; DX <- clear accumulator MemMaxFree4: add dx,PAGE_SIZE ; DX <- increase block size inc bx ; BX <- increase table offset cmp bl,PAGE_NUM ; check table end jne short MemMaxFree2 ; next block ; ------------- compare last free block cmp dx,ax ; block is bigger ? jb short MemMaxFree5 ; block is smaller xchg ax,dx ; AX <- found biggest block ; ------------- pop registers MemMaxFree5: pop dx ; pop DX pop bx ; pop BX ret ; ----------------------------------------------------------------------------- ; Get memory block module ; ----------------------------------------------------------------------------- ; INTPUT: AX = required size of memory block (0...) ; OUTPUT: AX = memory block size (MEM_SIZE8,...MEM_SIZEKB...) ; ----------------------------------------------------------------------------- ; ------------- push registers MemModule: push bx ; push BX push cx ; push CX ; ------------- small module cmp ax,PAGE_SIZE ; big memory block? ja short MemModule4 ; big memory block ; ------------- small memory block xchg ax,bx ; BX <- required size mov cx,8 ; CX <- smallest module reference mov ax,MEM_SIZE8 ; AX <- memory block module MemModule2: cmp cx,bx ; check size jae short MemModule8 ; module size is OK shl cx,1 ; CX <- increase module size inc ax ; AX <- increase module number jmp short MemModule2 ; try next module ; ------------- big memory block (multiple of KB) MemModule4: mov cl,PAGE_BITS ; CL <- number of bits per page add ax,PAGE_MASK ; AX <- round up to page shr ax,cl ; AX <- number of 1 KB memory blocks add al,MEM_KB_BIAS ; AX <- KB module ; ------------- pop registers MemModule8: pop cx ; pop CX pop bx ; pop BX ret ; ----------------------------------------------------------------------------- ; Allocate memory block ; ----------------------------------------------------------------------------- ; INTPUT: AX = required size of memory block (0...) ; OUTPUT: AX = address of memory block (NC), or 0 (NULL) on error (CY) ; CY = allocation error ; ----------------------------------------------------------------------------- ; ------------- get block module -> AX MemAlloc: call MemModule ; AX <- memory block module ; ------------- push registers push bx ; push BX push cx ; push CX push dx ; push DX push si ; push SI ; ------------- small memory block cmp al,MEM_SIZEKB ; small memory block? ja short MemAlloc6 ; large memory block ; ------------- number of memory blocks per one page -> AH mov cl,MEM_SIZEKB ; CL <- max. value sub cl,al ; CL <- number of rotations mov ah,1 ; AH <- bit mask shl ah,cl ; AH <- max. number of blocks per 1 KB ; ------------- find page with free blocks of this size xor bx,bx ; BX <- 0, address pointer mov si,MemSizeTab ; SI <- size table MemAlloc1: cmp [si],al ; check page size jne short MemAlloc2 ; invalid page size cmp [si-MemSizeTab+MemUsedTab],ah ; some free blocks? jb short MemAlloc4 ; found free blocks MemAlloc2: inc si ; SI <- increaze table pointer add bx,PAGE_SIZE ; BX <- shift address pointer cmp si,MemSizeTab+PAGE_NUM ; check table end jb short MemAlloc1 ; test next position ; ------------- create new page with this size xor bx,bx ; BX <- 0, address pointer mov si,MemSizeTab ; SI <- size table MemAlloc3: cmp byte [si],0 ; free page ? je short MemAlloc4 ; found free page inc si ; SI <- increaze table pointer add bx,PAGE_SIZE ; BX <- shift address pointer cmp si,MemSizeTab+PAGE_NUM ; check table end jb short MemAlloc3 ; test next position jmp short MemAlloc8 ; allocation error ; ------------- prepare address of bitmap table -> SI MemAlloc4: mov ah,0 ; AX = block size mov si,ax ; SI <- block size shl si,1 ; SI <- offset of table mov si,[si+MemBitMapAddr-2] ; SI <- address of table ; ------------- address in bitmap table -> SI mov cl,al ; AL <- block size add cl,2+3 ; CL <- 2 for size, 3 for bit mov dx,bx ; DX <- block address shr dx,cl ; DX <- offset it bitmap table add si,dx ; SI <- address in bitmap table ; ------------- block size -> DX sub cl,3 ; CL <- bits per block xor dx,dx ; DX <- 0 inc dx ; DX <- 1 shl dx,cl ; DX <- size of block ; ------------- find free block (from address BX) mov ah,1 ; AH <- bit mask MemAlloc5: test [si],ah ; test if block is free jz short MemAlloc7 ; found free block add bx,dx ; BX <- shift address rol ah,1 ; AH <- rotate mask adc si,byte 0 ; SI <- shift address jmp short MemAlloc5 ; ------------- large memory block (2 KB and more) MemAlloc6: xor bx,bx ; BX <- 0, address pointer mov si,MemSizeTab ; SI <- size table mov dl,al ; DL <- required size sub dl,MEM_KB_BIAS+1 ; DL <- number of KB blocks - 1 MemAlloc62: cmp byte [si],0 ; free page? jne short MemAlloc68 ; no ; ------------- check length of block string push si ; push SI mov dh,dl ; DH <- required size in KB blocks MemAlloc64: inc si ; increase table pointer cmp byte [si],0 ; free page? jne short MemAlloc66 ; invalid page dec dh ; counter of KB blocks jnz short MemAlloc64 ; try next block MemAlloc66: pop si ; pop SI je short MemAlloc7 ; found suiting block ; ------------- try next KB block MemAlloc68: inc si ; SI <- increase table pointer add bx,PAGE_SIZE ; BX <- shift address pointer cmp si,MemSizeTab+PAGE_NUM ; check table end jb short MemAlloc62 ; test next position jmp short MemAlloc8 ; allocation error ; ------------- mark this block as used MemAlloc7: call MemMark ; mark block as used xchg ax,bx ; AX <- block address jmp short MemAlloc9 ; ------------- error MemAlloc8: xor ax,ax ; AX <- 0, allocation error ; ------------- pop registers MemAlloc9: pop si ; pop SI pop dx ; pop DX pop cx ; pop CX pop bx ; pop BX cmp ax,1 ; check memory address ret ; ----------------------------------------------------------------------------- ; Resize memory block ; ----------------------------------------------------------------------------- ; INTPUT: AX = required new size of memory block (0 = delete block) ; BX = address of memory block (NULL = create new block) ; OUTPUT: AX = new address of memory block (NC), or 0 (NULL) on error (CY) ; CY = allocation error ; ----------------------------------------------------------------------------- ; ------------- new memory block MemResize: or bx,bx ; new memory block? jnz short MemResize2 ; not new memory block jmp MemAlloc ; allocate new memory block ; ------------- delete memory block MemResize2: or ax,ax ; delete block? jnz short MemResize3 ; size > 0 mov ax,bx ; AX <- address of memory block call MemFree ; delete memory block jc short MemResize22 ; error xor ax,ax ; AX <- destroy old memory address MemResize22: ret ; ------------- push registers MemResize3: push bx ; push BX push cx ; push CX push dx ; push DX push si ; push SI push di ; push DI xchg ax,si ; SI <- required new size of block ; ------------- get size of old memory block -> AX, DI mov ax,bx ; AX <- address of memory block call MemGetSize ; check old memory block jc short MemResize8 ; invalid memory block mov di,ax ; DI <- old size of memory block ; ------------- get old module of memory block -> DL call MemModule ; get memory block module xchg ax,dx ; DL <- old module of memory block ; ------------- get new module of memory block -> DH mov ax,si ; AX <- required new size call MemModule ; get memory block module mov dh,al ; DH <- new module of memory block ; ------------- check if size need to be changed cmp dh,dl ; size changed? je short MemResize7 ; size not changed ja short MemResize5 ; size needs to expand ; ------------- decreasing by 1 degree is OK dec dx ; DL <- old module - 1 cmp dh,dl ; size decreased by 1 degree? je short MemResize7 ; size needs not be changed inc dx ; DL <- old module ; ------------- decreasing small memory blocks needs to be copied cmp dl,MEM_SIZEKB ; small old module? jb short MemResize4 ; needs to copy cmp dh,MEM_SIZEKB ; small new module? jae short MemResize55 ; decrease large memory block ; ------------- decrease with copy MemResize4: mov cx,si ; CX <- required new size inc cx ; CX <- new size + 1 jmp short MemResize62 ; resize block ; ------------- expanding small memory blocks needs to be copied MemResize5: cmp dl,MEM_SIZEKB ; small old module? jb short MemResize6 ; needs to copy cmp dh,MEM_SIZEKB ; small new module? jb short MemResize6 ; needs to copy ; ------------- expand large memory block - check available space mov ax,bx ; AX <- memory block address mov cl,PAGE_BITS ; CL <- 10, size of 1 KB block shr ax,cl ; AX <- offset of descriptor add al,dl ; AL <- old module sub al,MEM_KB_BIAS ; AL <- end of old block add ax,MemSizeTab ; AX <- descriptor address xchg ax,bx ; AX <- address, BX <- descriptor MemResize52: cmp byte [bx],0 ; free block? jne short MemResize58 ; not free block inc bx ; BX <- next size descriptor inc dx ; DL <- increase old module cmp dl,dh ; new size reached? jne short MemResize52 ; try next block xchg ax,bx ; BX <- old address ; ------------- Re-mark large memory block MemResize55: mov ax,bx ; AX <- address of memory block call MemFreeNoCheck ; unmark old block mov al,dh ; AL <- required new size call MemMark ; mark memory block BX jmp short MemResize7 ; reuse old address ; ------------- expand with copy MemResize58: xchg ax,bx ; BX <- old address MemResize6: mov cx,di ; CX <- old size of memory block MemResize62: xchg ax,si ; AX <- required new size call MemAlloc ; allocate new memory block jc short MemResize8 ; memory error mov si,bx ; SI <- address of old block shr cx,1 ; CX <- old size / 2 mov di,ax ; DI <- address of new block rep movsw ; copy old content of block xchg ax,bx ; AX <- old address, BX <- new address call MemFreeNoCheck ; free old memory block ; ------------- old memory block suits OK MemResize7: xchg ax,bx ; AX <- old address of memory block clc ; clear error flag ; ------------- pop registers MemResize8: pop di ; pop DI pop si ; pop SI pop dx ; pop DX pop cx ; pop CX pop bx ; pop BX ret ; ----------------------------------------------------------------------------- ; Duplicate memory block ; ----------------------------------------------------------------------------- ; INTPUT: BX = address of memory block (NULL = create new block) ; OUTPUT: AX = address of new memory block (NC) or 0 (NULL) on error (CY) ; CY = allocation error ; ----------------------------------------------------------------------------- ; ------------- push registers MemDup: push cx ; push CX push si ; push SI push di ; push DI ; ------------- get size of memory block -> AX, CX mov ax,bx ; AX <- block address call MemGetSize ; get size of memory block jc short MemDup9 ; invalid memory block mov cx,ax ; CX <- size of memory block ; ------------- create new memory block call MemAlloc ; allocate new memory block jc short MemDup9 ; memory error ; ------------- copy block content (it clears CF, block size is even) mov si,bx ; SI <- address of old block mov di,ax ; DI <- address of new block shr cx,1 ; CX <- size of memory block / 2 rep movsw ; copy block content ; ------------- pop registers MemDup9: pop di ; pop DI pop si ; pop SI pop cx ; pop CX ret ; ----------------------------------------------------------------------------- ; Constant data ; ----------------------------------------------------------------------------- CONST_SECTION ; ------------- address of bit map tables align 2, db 0 MemBitMapAddr: dw MemBitMap8 ; 8 byte blocks dw MemBitMap16 ; 16 byte blocks dw MemBitMap32 ; 32 byte blocks dw MemBitMap64 ; 64 byte blocks dw MemBitMap128 ; 128 byte blocks dw MemBitMap256 ; 256 byte blocks dw MemBitMap512 ; 512 byte blocks dw MemBitMap1K ; 1KB blocks ; ----------------------------------------------------------------------------- ; Uninitialised data ; ----------------------------------------------------------------------------- DATA_SECTION ; ------------- memory statistic align 2, resb 1 MemFreeTotal: resw 1 ; total free memory MemUsedTotal: resw 1 ; total used memory ; ============= tables (reinitialised to 0) TablesStart: ; start of tables to clear ; ------------- table of block sizes of blocks in pages, 0=free align 2, resb 1 MemSizeTab: resb PAGE_NUM ; 0=free, 1..7=8..512 bytes, 8..=in KB ; ------------- table of number of allocated blocks in pages, 0=free MemUsedTab: resb PAGE_NUM ; 0=free, ... max. 128 for 8B blocks ; ------------- bit map of used blocks, 1=used (uses 2 KB of memory) align 2, resb 1 MemBitMap: MemBitMap8: resb 1024 ; 8 byte blocks MemBitMap16: resb 512 ; 16 byte blocks MemBitMap32: resb 256 ; 32 byte blocks MemBitMap64: resb 128 ; 64 byte blocks MemBitMap128: resb 64 ; 128 byte blocks MemBitMap256: resb 32 ; 256 byte blocks MemBitMap512: resb 16 ; 512 byte blocks MemBitMap1K: resb 8 ; 1KB blocks align 2, resb 1 TablesEnd: ; end of tables to clear