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

📄 mem.asm

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

;         LoadVMTSeg es,bx

@@check:
         call ds:[si] method memory_block:IsFree
;         cmp word ptr ds:[si.next],FREE_BLOCK  ; See if this block is free
         jz  @@found

         ; It's not free. So go to the next block.
         call ds:[si] method memory_block:GetNext
         IsZero  ax     ; Check for the last block in the chain (next=0?)
         jz  @@done
         mov ds,ax
         jmp @@check

@@found:
         ; Load the size of the current block into AX
         ; Size in paragraphs is    (seg of next block) - (seg of this block)
         mov  ax,ds
         neg  ax
         add  ax,word ptr ds:[si.next2]
         dec  ax       ; Adjust for block bookkeeping information
;         mov  ax,ds:[si.blksize]   ; This should produce the same
                                    ; value for free blocks.

@@done:
         ret
mb_scan endp


mb_rawblocksize proc
;         LoadVMTSeg es,bx
         call ds:[si] method memory_block:GetNext
         mov  bx,ds
         sub  ax,bx
         ret
mb_rawblocksize endp



mb_breakblock proc uses ds si
         local desiredsize:word,currentnext:word,newnext:word,currblock:word,\
               newblocksize:word

         mov  [desiredsize],ax
         mov  ax,ds
         mov  [currblock],ax
         mov  [newnext],ax     ; We'll use newnext as the address to return in
                               ; AX.

         ; This routine is only valid for free memory blocks
;         LoadVMTSeg es,bx
ifdef _DO_ISFREE_
         call ds:[si] method memory_block:IsFree
         jnz  @@done
endif

         call ds:[si] method memory_block:RawBlockSize
         mov  bx,ax
         sub  bx,[desiredsize]
         dec  bx     ; Represent bookkeeping information of current block
         dec  bx     ; For bookkeeping information of the new block
         mov  [newblocksize],bx
         cmp  bx,2   ; If less than four paragraphs left over, don't
                     ; do the breakdown.
         jbe  @@done

         ; Get the current next block
         call ds:[si] method memory_block:GetNext
         mov  [currentnext],ax

         ; Calculate the segment of the new block
         mov  ax,ds
         add  ax,[desiredsize]
         inc  ax             ; For the size of our bookkeeping info
         mov  [newnext],ax

         ; Set our next pointer to new block
         call ds:[si] method memory_block:SetNext

         ; Set our size
         mov  ax,[desiredsize]
         call ds:[si] method memory_block:SetSize

         ; Set the new block to point to its neighbors
         mov  ds,[newnext]
         call ds:[si] method memory_block:init pascal,[currblock],[currentnext],[newblocksize]

ifdef _DO_SETPREV_
         ; Set the old next block to point to the new block created just
         ; before it.
         mov  ds,[currentnext]
         call ds:[si] method memory_block:setprev
endif

@@done:
         mov  ax,[newnext]
         ret
mb_breakblock endp



memory_block_markfree proc
ifdef _DO_ISFREE_
         local previous:word

         mov  [previous],ax
         call ds:[si] method memory_block:IsFree
         jz   @@block_is_free_skip

         ; Get the pointer to the next block
         call ds:[si] method memory_block:GetNext

         ; Calculate the size of this block
         push ax

         mov  bx,ax
         mov  ax,ds
         sub  bx,ax
         dec  bx      ; For the bookkeeping area

         pop  ax
         call ds:[si] method memory_block:init  pascal,[previous],ax,bx

@@block_is_free_skip:
endif
         ret
memory_block_markfree endp



memory_block_markused proc
ifdef _DO_ISFREE_
         call ds:[si] method memory_block:IsFree
         jnz  @@done
endif
         mov  ax,word ptr ds:[si.next2]
         mov  word ptr ds:[si.next],ax
         mov  ax,word ptr ds:[si.next2+2]
         mov  word ptr ds:[si.next+2],ax

         ; Change the block type to be a used block.
         ; Do this by changing the VMT!
         mov  ds:[si.@Mptr_memory_block],offset @TableAddr_memory_usedblock
;if @CodeSize eq 1
;         mov  word ptr ds:[si.@Mptr_memory_block+2],seg @TableAddr_memory_usedblock
;endif
@@done:
         ret
memory_block_markused endp



memory_block_lock proc

         ret
memory_block_lock endp



memory_block_unlock proc

         ret
memory_block_unlock endp


memory_block_allocfail proc
         ret
memory_block_allocfail endp


page
;***** Routines for  MEMORY_USEDBLOCK


memory_usedblock_markfree proc
         local previous:word

         mov  [previous],ax
ifdef _DO_ISFREE_
         call ds:[si] method memory_block:IsFree
         jz   @@block_is_free_skip
endif

         ; Get the pointer to the next block
         call ds:[si] method memory_block:GetNext

         ; Calculate the size of this block
         push ax

         mov  bx,ax
         mov  ax,ds
         sub  bx,ax
         dec  bx      ; For the bookkeeping area

         pop  ax
         call ds:[si] method memory_block:init  pascal,[previous],ax,bx

@@block_is_free_skip:
         ret
memory_usedblock_markfree endp


memory_usedblock_combine proc
         ret    ;Can't do a combine with a used block. So ignore it!
memory_usedblock_combine endp



memory_usedblock_setnext proc
         mov  word ptr ds:[si.next],ax
         ret
memory_usedblock_setnext endp



memory_usedblock_invalid proc
         ret
memory_usedblock_invalid endp



memory_usedblock_isfree proc uses ax
         mov  ax,1    ; Set the Z flag to zero!
         IsZero ax
         ret
memory_usedblock_isfree endp



memory_usedblock_scan proc
         ; This block is not free, so quickly pass the call
         ; along to the next object in this chain!
         mov   ax,word ptr ds:[si.next]
         mov   ds,ax
         IsZero ax   ; Check for zero, meaning end of the line!
         jz    @@done

         ; Use a jump, instead of
         ; call  ds:[si] method memory_usedblock:ScanFree
         ; so that we eliminate overflowing the stack during this routine.
         MOV   BX,ds:[([ SI ]).@Mptr_memory_block]
;if @CodeSize eq 1
;         MOV   ES,word ptr [([DS :SI ]).@Mptr_memory_block+2]
;endif
         jmp   es:[(@Table_memory_usedblock PTR BX).ScanFree]

@@done:
         ret
memory_usedblock_scan endp



memory_usedblock_getnext proc
         mov  ax,word ptr ds:[si.next]
         ret
memory_usedblock_getnext endp



memory_usedblock_init proc
         ; Set the VMT PTR within this block!
         mov  ds:[si.@Mptr_memory_block],offset @TableAddr_memory_usedblock
         ret
memory_usedblock_init endp



memory_usedblock_show proc uses ds es dx ax
.data
@@type db "USED$"
@@next db " Next:$"
.code
         call Show_Bracket
         push ds
         pop  es
         mov  ax,@data
         mov  ds,ax
         mov  dx,offset @@type
         mov  ah,DOSPRINTSTRING
         int  DOSINT

         mov  ah,DOSPRINTSTRING
         mov  dx,offset @@next
         int  DOSINT
         mov  ax,word ptr es:[si.next]
         call ShowHexWord

         call Show_Endbracket
         ret
memory_usedblock_show endp



memory_usedblock_lock proc

         ret
memory_usedblock_lock endp



memory_usedblock_unlock proc

         ret
memory_usedblock_unlock endp




page
;***** Routines for   MEMORY_ENDBLOCK


memory_endblock_ignore proc
         ret
memory_endblock_ignore endp



memory_endblock_getnext proc
         xor ax,ax
         ret
memory_endblock_getnext endp



memory_endblock_init proc
         ; Set the VMT PTR within this block!
         mov  ds:[si.@Mptr_memory_block],offset @TableAddr_memory_endblock
;if @CodeSize eq 1
;         mov  word ptr ds:[si.@Mptr_memory_block],seg @TableAddr_memory_endblock
;endif
         xor  ax,ax
         mov  word ptr ds:[si.next],ax
         mov  word ptr ds:[si.next+2],ax
         ret
memory_endblock_init endp


memory_endblock_show proc uses ds dx ax
.data
@@end db "END$"
.code
         call Show_Bracket
         mov  ax,@data
         mov  ds,ax
         mov  dx,offset @@end
         mov  ah,DOSPRINTSTRING
         int  DOSINT

         call Show_Endbracket
         ret
memory_endblock_show endp





page
;***** Routines for   MEMORY_SYSTEM


memory_system_init proc uses es ds si bx
         local endblockseg:word

         ; Fill in the VMT for the memory system
         mov  ds:[si.@Mptr_memory_system],offset @TableAddr_memory_system

         ; Get a block of memory.
         mov  bx,ax              ; Get the desired size, unless it is zero,
                                 ; then get the largest possible block.
         or   bx,bx
         jnz  @Memory_system_init_Alloc

         dec  bx   ;mov  bx,0FFFFh          ; Go for largest possible
@Memory_system_init_Alloc:
         mov  ds:[si.blocksize],bx
         mov  ah,DOSGETMEMBLOCK
         int  DOSINT

         ; Need to handle fail here!  (Carryflag set, and BX with size of
         ;                              largest block available. )
         jnc  AllocSuccess

         ; Check the high bit of blocksize to see
         ; if we can get a different size.
         ; Note that if we come here a second time, it is because DOS
         ; said a certain size was available, and then it wouldn't give
         ; it when requested. The high bit wont be set on the second call.
         TESTFLAG ds:[si.blocksize],8000h
         jz   AllocFailed

         ; BX has size of largest block available. Go get it if it is NZ.
         or   bx,bx
         jnz  @Memory_system_init_Alloc    ; Jump back and get it if there
                                           ; is some available.
AllocFailed:
         mov  ds:[si.blocksize],0
         jmp  @Memory_system_init_done

AllocSuccess:
         ; Success:  Carryflag clear, and AX initial segment of allocated block

         mov  [si.root],ax     ; Segment of start of block still in AX!

         mov  [si.rover],ax

         ; Load the size of the block into BX
         mov  bx,ds:[si.blocksize]
         dec  bx     ; For bookkeeping
         dec  bx     ; For the endblock

         ; Calculate in CX the segment of the endblock
         mov  cx,bx
         inc  cx     ; For bookkeeping for first block
         add  cx,ax  ; To get segment
         mov  [endblockseg],cx
         mov  [si.last],cx


         ; Save the address of the memory system, so we
         ; can call constructor for the memory block.
         push ds
         push si

         ; Load the pointer to the block into DS:SI
         mov  ds,ax
         xor  si,si
         xor  ax,ax   ; For pushing zeros for prev & next blocks

;         ; Need to set the VMT for the memory block before calling init!
;         ; This is only needed if INIT routine is in the VMT!
;         mov  ds:[si.@Mptr_memory_block],offset @TableAddr_memory_block

         LoadVMTSeg ES
         call ds:[si] method memory_block:init pascal, ax,cx,bx

         ; Now make an endblock
         mov  ds,[endblockseg]
         call ds:[si] method memory_endblock:init


         ; Restore pointre to the memory system
         pop  si
         pop  ds

@Memory_system_init_done:
         mov  ds:[si.usedspace],0
         mov  ax,ds:[si.blocksize]
         dec  ax    ; Bookkeeping for the first block
         dec  ax    ; Bookkeeping for the end block
         mov  ds:[si.freespace],ax
         dec  ds:[si.freespace]

⌨️ 快捷键说明

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