⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.asm

📁 还是一个词法分析程序
💻 ASM
📖 第 1 页 / 共 3 页
字号:
         ret
memory_system_init endp



memory_system_deinit proc
        ; Return the memory to DOS.
         mov  es,ds:[si.root]
         mov  ah,DOSRELEASEBLOCK
         int  DOSINT
         ret
memory_system_deinit endp



memory_system_resetrover proc
         mov  bx,ds:[si.root]
         mov  ds:[si.rover],root
         ret
memory_system_resetrover endp



.data
mss_initial  db "Memory System Show:",CR,LF
             db "System at:$"
mss_root     db "  Root block at:$"
mss_last     db "  Last block at:$"
mss_rover    db " Rover block at:$"
mss_free     db "      Freespace:$"
mss_used     db "      Usedspace:$"
mss_blocks   db "Blocks at:$"
mss_no_blks  db "No blocks in heap.$"
.code
memory_system_show   proc uses ax dx es ds
         ; Move pointer to the memory system from DS:SI, to ES:SI
         push  ds
         pop   es
         ; Now load pointer to our messages
         mov   dx,@data
         mov   ds,dx
         ; Show the location of the memory system
         mov   dx,offset mss_initial
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es
         call  ShowHexWord
         mov   dl,':'
         mov   al,DOSPRINTCHAR
         int   DOSINT
         mov   ax,si
         call  ShowHexWord
         call  CRLF

         ; Show the internal variables of the memory system
         mov   dx,offset mss_root
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es:[si.root]
         call  ShowHexWord
         call  CRLF
         mov   dx,offset mss_last
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es:[si.last]
         call  ShowHexWord
         call  CRLF
         mov   dx,offset mss_rover
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es:[si.rover]
         call  ShowHexWord
         call  CRLF
         mov   dx,offset mss_free
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es:[si.freespace]
         call  ShowHexWord
         call  CRLF
         mov   dx,offset mss_used
         mov   ah,DOSPRINTSTRING
         int   DOSINT
         mov   ax,es:[si.usedspace]
         call  ShowHexWord
         call  CRLF

         ; Save pointer to the memory system
         push  es
         push  si
         mov   ax,es:[si.root]
         xor   si,si

         ; Check for empty chain
         cmp   ax,0
         jz    mss_no_blocks

         push  ax

         ; Now we need to walk the chain
         mov   dx,offset mss_blocks
         mov   ah,DOSPRINTSTRING
         int   DOSINT

         pop   ax


mss_show_block:
         mov   ds,ax
         call  ShowHexWord

         LoadVMTSeg ES,AX
         call  ds:[si] method memory_block:show

         call  ds:[si] method memory_block:GetNext
         ; See if it is the last block
         IsZero ax
         jz    mss_show_block_done
         push  ax
         mov   ah,DOSPRINTCHAR
         mov   dl,','
         int   DOSINT
         pop   ax
         jmp   mss_show_block

; Branch here if this heap system is still empty
mss_no_blocks:
         mov   dx,offset mss_no_blks
         mov   ah,DOSPRINTSTRING
         int   DOSINT

mss_show_block_done:
         pop   si
         pop   es

         call  CRLF

         ret
memory_system_show   endp



memory_system_freeall   proc
         mov  ax,[si.root]
@@free_another:
         ; If it is the end block, dont try to free it.
         cmp  ax,ds:[si.last]
         jz   @@done
         push ax
         call ds:[si] method memory_system:free
         pop  ax
         push ds
         push si
         mov  ds,ax
         xor  si,si
         call ds:[si] method memory_block:GetNext
         IsZero ax
         pop  si
         pop  ds
         jnz  @@free_another
@@done:
         ret
memory_system_freeall   endp



memory_system_findprev  proc uses ds si
;         local systemseg:word,systemofs:word,findprevfor:word
;         mov  [systemseg],ds
;         mov  [systemofs],si
;         mov  [findprevfor],ax

         ; Check if this block is the root block
         cmp  ax,[si.root]
         jz   @memory_system_findprev_atroot

         ; Make pointer to first block in memory system
         mov  ds,[si.root]
         xor  si,si

         call [si] method memory_block:MatchNext
         cmp  ax,0
         jne  @memory_system_findprev_done

         ; The block wasn't found!

@memory_system_findprev_atroot:

@memory_system_findprev_done:
;         mov ds,[systemseg]
;         mov si,[systemofs]
         ret
memory_system_findprev  endp



memory_system_blockofs proc uses ds si
         cmp  ax,0
         jne  @memory_system_blockofs_getit
         mov  ax,ds:[si.root]  ; Get the root and use it's offset since
                               ; no segment was passed in
@memory_system_blockofs_getit:
         mov  ds,ax
         xor  si,si
         call ds:[si] method memory_block:memstart
         ret
memory_system_blockofs endp



memory_system_alloc proc uses ds si
         local allocsize:word,\
               allocblock:word,\
               largest:word,\      ; The size of the largest block encountered
               largestseg:word,\
               newfree:word,\
               rootscan:word,\
               memsysaddr:dword

         mov  [largest],0
         mov  [rootscan],0

         mov  word ptr [memsysaddr],si
         mov  word ptr [memsysaddr+2],ds

         mov  [allocsize],ax
ifdef _USE_ROVER_
         mov  ax,ds:[si.rover]
else
         mov  ax,ds:[si.root]
endif
         mov  ds,ax
@@scan:
         xor  si,si
         call ds:[si] method memory_block:ScanFree
         ; Check if there is enough room in this free block
         cmp  ax,[largest]
         jbe  @@scan_2
         mov  [largest],ax
         mov  [largestseg],ds
@@scan_2:
         cmp  ax,[allocsize]
         ja   @@found
         mov  ax,ds
         IsZero ax
         je   @@no_more_blocks
         call ds:[si] method memory_block:GetNext
         IsZero ax
         je   @@no_more_blocks


         ; The following block may also be free. Try to combine them.
         ; Swap DS and AX
         mov  bx,ds   ; DS has the previous block!
         mov  ds,ax
         mov  ax,bx   ; Make sure AX has the previous block
         call ds:[si] method memory_block:Combine

         jmp  @@scan

         ; No more blocks to scan!
@@no_more_blocks:
ifdef _USE_ROVER_
         ; Scan again from the root, because a big enough
         ; block could be prior to rover.
         cmp  [rootscan],0
         jne  @@scan_root

         inc  [rootscan]
         lds  si,dword ptr [memsysaddr]
         mov  ax,ds:[si.root]

         ; Check to see that rover wasn't already pointing at the root
         cmp  ax,ds:[si.rover]
         je   @@scan_root

         mov  ds,ax
         jmp  @@scan

@@scan_root:
endif
         ; Set rover to point to this new largest memory block,
         ; because combines might have invalidated the rover pointer.
         lds  si,dword ptr [memsysaddr]
         mov  ax,[largestseg]
         mov  ds:[si.rover],ax
         xor  ax,ax
         mov  bx,[largest]
         jmp  @@done

@@found:
         mov  [allocblock],ds
         ; See how much is leftover in the block after the memory needed
         ; for this alloc call is taken out
         mov  ax,[allocsize]
         call ds:[si] method memory_block:BreakBlock
ifdef _USE_ROVER_
         mov  [newfree],ax
endif
         ; Mark the block as used!
         call ds:[si] method memory_block:MarkUsed
         call ds:[si] method memory_block:LockBlock
         call ds:[si] method memory_block:memstart
         push bx

         ; If enough area was leftover, the extra area has been
         ; broken off to make a separate block.
         lds  si,dword ptr [memsysaddr]
ifdef _USE_ROVER_
         ; Update rover
         mov  ax,[newfree]
         mov  ds:[si.rover],ax
endif

         mov  ax,[allocblock]
         pop  bx
;         call ds:[si] method memory_block:memstart
@@done:
         ret
memory_system_alloc endp



memory_system_free proc uses ds si bx
         local prevblock:word,\  ; Address of the block previous to this one
               freeblock:word,\  ; Address of block that is being freed
               systemaddr:dword

         mov  word ptr [systemaddr],si
         mov  word ptr [systemaddr+2],ds
         mov  [freeblock],ax

         cmp  ax,0
         jz   @@done

         ; Check the block to make sure that it is not already free
         ; Note that an invalid block address here will likely hang the
         ; memory manager, since the VMT will not be valid.
         mov  ds,ax
         xor  si,si
ifdef _DO_ISFREE_
         call ds:[si] method memory_block:IsFree
         jz   @@done
endif
         call ds:[si] method memory_block:UnLockBlock

         lds  si,dword ptr [systemaddr]
         mov  ax,[freeblock]
         cmp  ax,ds:[si.root]
         je   @@free_root      ; Special routine to free the root block

ifdef _COMBINE_PREVIOUS_
         ; Prior to freeing the block, get the address of
         ; the previous block. If no previous block is found,
         ; then this is a bogus FREE request and will be ignored.
         call ds:[si] method memory_system:findprev
         IsZero ax   ; Check for zero.
         jz   @@done

         ; There is a previous block
         mov  [prevblock],ax
endif

         ; Mark the current block as free.
         mov  ds,[freeblock]
         xor  si,si
         call ds:[si] method memory_block:MarkFree

ifdef _COMBINE_PREVIOUS_
         mov  ds,[prevblock]
         xor  si,si
         call ds:[si] method memory_block:IsFree
         mov  ds,[freeblock]
         jnz  @@try_combine_next
else
         jmp  @@try_combine_next
endif

@@combine_previous:
         ; The previous block is free, therefore it can be combined with
         ; this one. Set the previous block to point to our next block.
         call ds:[si] method memory_block:GetNext
         mov  ds,[prevblock]
         call ds:[si] method memory_block:SetNext
         ; Also, need to update size of previous block
         ; AX still contains seg of block after one being freed.
         mov  bx,ds
         sub  ax,bx
         dec  ax
         call ds:[si] method memory_block:SetSize
         mov  [freeblock],ds
         jmp  @@try_combine_next

@@free_root:
         ; At this point we only have to worry is if the block following
         ; a free block so it can be combined with this one.
         ; AX is the block to free.
         mov  ds,ax
         xor  si,si
         xor  ax,ax     ; Because there is not previous block
         call ds:[si] method memory_block:MarkFree

@@try_combine_next:
         call ds:[si] method memory_block:GetNext
         mov  ds,ax
         call ds:[si] method memory_block:IsFree
         jnz  @@No_more_combine
         mov  ax,[freeblock]
         mov  [prevblock],ax
         jmp  @@combine_previous

@@No_more_combine:
ifdef _USE_ROVER_
        ; Just in case the rover might have pointed to a block that was
        ; combined with another, set rover to the start of the new
        ; free block that was created.
         lds  si,dword ptr [systemaddr]
         mov  bx,[freeblock]
         mov  ds:[si.rover],bx
endif


@@done:
         ret
memory_system_free endp


.data
LastSeg dw seg zzlastseg


.code
shrink_memory proc
     ; Have to give up extra memory that we don't need
     ; so the memory system objects can get blocks of memory.
     mov  bx,[LastSeg]
     mov  ax,es
     sub  bx,ax    ; Size of program as a number of segments is in BX
     mov  ah,DOSRESIZEBLOCK
     int  DOSINT

         ret
shrink_memory endp



zzlastseg segment

zzlastseg ends

end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -