📄 memory.asm
字号:
;-------------------------------------------------------------------------------
;
;Get memory using RAW/VCPI.
;
;On Entry:-
;
;BX:CX - Size of block.
;
;On Exit:-
;
;Carry on error else,
;
;SI:DI - Handle.
;BX:CX - Logical address of block.
;
RAWGetMemory proc near
call RAWCopyCheck
;
pushm eax,edx,ebp,ds,es
mov ax,KernalDS ;make data addresable.
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
shl ebx,16 ;get block size as 32-bit.
mov bx,cx
add ebx,4095 ;round up to next 4k.
shr ebx,12
or ebx,ebx
jz @@error
@@start: mov edi,LinearBase ;Get starting point.
mov ecx,LinearLimit
sub ecx,edi ;Get memory present.
shr ecx,12 ;Get pages.
shr edi,12 ;Get page number.
shl edi,2 ;dword per entry.
add edi,1024*4096*1022 ;point to page details.
;
;Look for a big enough block of free memory.
;
xor eax,eax ;value to look for.
cld
;
;EAX - zero, what we're looking for.
;ECX - entries to check.
;EDI - address of entries to check.
;
;EBX - number of entries we want.
;
@@l0: repne scasd
;
;Nothing found means extend end of memory map.
;
jnz @@ExtendNew
;
;Point everything back to the matching value.
;
sub edi,4
inc ecx
;
;Save current position as start of last free block incase
;this block extends to the end of memory.
;
mov esi,edi ;save last position.
;
;If we only wanted one page then we're done, this is it!
;
cmp ebx,1
jz @@l2 ;Speed up 4K allocations.
;
;Set the number of pages to scan. This should be the number of
;pages we want but has to be reduced to the number of pages
;actually available when the request would go off the end of
;memory.
;
mov edx,ebx
cmp ecx,ebx ;Enough space to check?
jnc @@l1
mov edx,ecx
;
;Scan specified number of entries to see if their all free.
;
@@l1: pushm ecx,edi
mov ecx,edx
repe scasd ;Scan for free pages.
popm ecx,edi
jnz @@l3 ;not enough free entries.
;
;All the entries were free, now check if we were truncating the
;length to stop us running off the end of memory.
;
cmp edx,ebx ;Truncated length?
jnz @@ExtendEnd
jmp @@l2
;
;One way or another we didn't find the number of entries we were
;after so restart the search.
;
@@l3: add edi,4
dec ecx
jmp @@l0
;
;We've found what we wanted without any extra messing around so
;hand this over to the marker.
;
@@l2: sub esi,1024*4096*1022 ;point to page details.
shr esi,2
jmp @@MarkMemRet
;
;Last block is free so use it as the basis for extension.
;
@@ExtendEnd: mov edi,ecx ;remaining entries.
sub esi,(1024*4096*1022)
shr esi,2 ;Get start page number.
mov ecx,ebx ;Total pages needed.
sub ecx,edi ;Pages found so far.
jmp @@Extend
;
@@ExtendNew: ;Last block not free so new block will start at LinearLimit.
;
mov ecx,ebx ;Set pages needed.
mov esi,LinearLimit ;New start address.
shr esi,12
;
@@Extend: ;Memory map needs extending so get on with it.
;
call ExtendLinearMemory ;Try and extend memory map.
jnc @@MarkMemRet ;Mark the block as used.
;
;Not enough memory so report failure.
;
stc
jmp @@exit
;
@@MarkMemRet: ;Got the memory so mark it in use.
;
sub FreePages,ebx ;reduce free page count.
add medAllocPages,ebx
;
mov ecx,ebx ;Get number of pages again.
mov edx,esi
mov edi,esi ;Get base page again.
shl edi,2
add edi,1024*4096*1022
mov eax,MEM_END
rep stosd
mov es:d[(1024*4096*1022)+edx*4],MEM_START
;
;Now return details to caller.
;
shl esi,12 ;Convert back to a real address.
mov di,si
shr esi,16
mov cx,di
mov bx,si
clc
jmp @@exit
;
@@error: stc
;
@@exit:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,edx,ebp,ds,es
ret
assume ds:_cwDPMIEMU
RAWGetMemory endp
;-------------------------------------------------------------------------------
;
;Re-size a block of memory.
;
;On Entry:-
;
;SI:DI - Handle.
;BX:CX - New block size.
;
;On Exit:-
;
;SI:DI - New handle.
;BX:CX - New address.
;
RAWResMemory proc near
call RAWCopyCheck
;
pushm eax,edx,ebp,ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
shl esi,16
mov si,di ;Get real address.
shl ecx,16
mov cx,bx
ror ecx,16
add ecx,4095
shr ecx,12 ;Get new block size.
or ecx,ecx
jz @@error
;
;Check for a valid address.
;
test esi,4095 ;all memory on page boundaries.
jnz @@error
cmp esi,LinearBase
jc @@error
cmp esi,LinearLimit
jnc @@error
shr esi,12 ;Get page number.
mov eax,es:d[1024*4096*1022+esi*4]
and eax,MEM_MASK
cmp eax,MEM_START
jnz @@error
;
;Work out the blocks current size.
;
push ecx
mov ebp,1
mov edx,esi
inc edx
mov ecx,LinearLimit
shr ecx,12
sub ecx,edx
jz @@l1
@@l0: mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_END
jnz @@l1
inc ebp
inc edx
dec ecx
jnz @@l0
;
@@l1: ;Shrinking or expanding?
;
pop ecx
cmp ecx,ebp
jz @@RetNewAddr
jnc @@Bigger
;
@@Smaller: ;Shrinking the block so get on with it.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
mov edx,esi
add edx,ecx ;move to new block end.
sub ebp,ecx ;get number of pages to lose.
mov ecx,ebp
;
add FreePages,ebp ;update number of free pages.
sub medAllocPages,ebp
;
@@s0: and es:d[(1024*4096*1022)+edx*4],not MEM_MASK
or es:d[(1024*4096*1022)+edx*4],MEM_FREE
and es:d[(1024*4096*1023)+edx*4],not (1 shl 6)
inc edx
dec ecx
jnz @@s0
call EMUCR3Flush
jmp @@RetNewAddr
;
@@Bigger: ;Want to expand the block so get on with it.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
@@b0: mov edx,esi
add edx,ebp ;move to end of this block.
mov ebx,LinearLimit
shr ebx,12
sub ebx,edx ;get pages to end of memory.
or ebx,ebx
jz @@Extend
;
;See if the next block is free.
;
mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_FREE
jnz @@NewBlock ;no hope so get a new block.
;
;Check how big this next block is.
;
mov edi,ebp ;use current size as basis.
@@b1: mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_FREE
jnz @@NewBlock ;No hope so get a new block.
inc edi
cmp edi,ecx ;Got enough yet?
jz @@MarkAndRet
inc edx
dec ebx
jnz @@b1 ;keep trying.
;
;Reached the end of the memory map so try extending it.
;
pushad
sub ecx,edi ;pages still needed.
call ExtendLinearMemory
popad
jc @@error
jmp @@MarkAndRet
;
@@Extend: ;Need to extend the memory map to provide a block of free memory
;after the current block.
;
pushad
sub ecx,ebp ;pages needed.
call ExtendLinearMemory
popad
jc @@error
;
@@MarkAndRet: ;Mark the new memory as in use and exit.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
mov edx,esi
add edx,ebp ;move to start of new memory.
sub ecx,ebp ;pages to mark.
;
sub FreePages,ecx ;update number of free pages.
add medAllocPages,ecx
;
@@mr0: and es:d[(1024*4096*1022)+edx*4],not MEM_MASK
or es:d[(1024*4096*1022)+edx*4],MEM_END
inc edx
dec ecx
jnz @@mr0
jmp @@RetNewAddr
;
@@NewBlock: ;Nothing for it but to try and allocate a new block of memory.
;
pushm ecx,ebp,esi
shl ecx,12
mov ebx,ecx
shr ebx,16
call RawGetMemory
pushf
shl ebx,16
mov bx,cx
popf
popm ecx,ebp,esi
jc @@error
;
;Copy current block to new block.
;
pushad
mov ecx,ebp
shl ecx,12
shl esi,12
mov edi,ebx
pushm ds,es
pop ds
shr ecx,2
rep movsd
pop ds
popad
;
;Release current block.
;
pushad
shl esi,12
mov di,si
shr esi,16
call RawRelMemory
popad
;
;Use new block in place of origional.
;
mov esi,ebx
shr esi,12
;
@@RetNewAddr: ;Return possibly new address/handle to caller.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -