📄 memcode.inc
字号:
PUSH EBX ;(save for caller)
PUSH ECX ;
PUSH EDX ;
PUSH ESI ;
PUSH EDI ;
;This first section sets to make [ESI] point to first PT that
;we have to move the other guy's physical pages into
MOV ECX, EBX ;Copy number of pages to ECX (EBX free to use).
MOV EDX, EAX ;LinAdd to EDX
SHR EDX, 22 ;Get index into PD for first PT
SHL EDX, 2 ;Make it index to DWORDS
PUSH EAX ;Save EAX thru GetpCrntJCB call
CALL GetpCrntJCB ;Leaves pCrntJCB in EAX
MOV ESI, [EAX.JcbPD] ;ESI now has linear address of PD
POP EAX ;Restore linear address
ADD ESI, 2048 ;Offset to shadow addresses in PD
ADD ESI, EDX ;ESI now points to first PT of interest
MOV EDX, EAX ;LinAdd into EDX again
AND EDX, 003FF000h ;get rid of upper 10 bits & lower 12
SHR EDX, 10 ;Index into PD for PT (10 vice 12 -> DWORDS)
ALR0:
MOV EDI, [ESI] ;Linear address of crnt page table into EDI
;At this point, EDI is pointing to the PT we are in.
;SO... EDI+EDX will point to the next PTE to do.
;Now we must call LinToPhy with Linear Add & JobNum
; to get a physical address into EAX.
;This is the Physical address to store in the new PTE. We must
;mark it MEMALIAS before adding it to PT.
ALR1:
PUSH ESI ;Save for next loop (used by LinToPhy)
MOV EAX, AliasJob ;Job we are aliasing
MOV EBX, AliasLin ;Address we are aliasing
ADD AliasLin, 4096 ;Set up for next loop (post increment)
CALL LinToPhy ;
;EAX now has physical address for this page
;
AND EAX, 0FFFFF000h ;cut off system bits of PTE
OR EAX, MEMALIAS ;Set system bits as ALIAS
POP ESI ;Restore ESI (LinToPhy used it)
;Now store it in new PTE
MOV DWORD PTR [EDI+EDX], EAX ;EDX is index to exact entry
DEC ECX ;Are we done??
JZ ALRDone
ADD EDX, 4 ;Next PTE please...
CMP EDX, 4096 ;Are we past last PTE of this PT?
JB ALR1 ;No, go do next PTE
ADD ESI, 4 ;Yes, next PDE (to get next PT)
XOR EDX,EDX ;Start at the entry 0 of next PT
JMP SHORT ALR0 ;
ALRDone:
POP EDI ;
POP ESI ;
POP EDX ;
POP ECX ;
POP EBX ;
MOV ESP,EBP ;
POP EBP ;
RETN
;=============================================================================
; AddUserPT
; This creates a new User Page Table, initializes it and sticks it
; in the Users's PD (in User Address space above 1GB).
; This is easier than AddOSPT because there is no need to update
; anyone else's PDs! This sets the protection on the PT to user
; Read & Write. Individual PTEs will be set read only for code.
;
; IN : Nothing
; OUT: 0 if OK or Error (ErcNoMem - no free phy pages!)
; USED: EAX, EFlags
;
AddUserPT:
PUSH EBX ;(save for caller)
PUSH ECX ;
PUSH EDX ;
PUSH ESI ;
PUSH EDI ;
MOV EAX, _nPagesFree ;See if have enuf physical memory
OR EAX, EAX
JNZ AUPT01
MOV EAX, ErcNoMem ;Sorry, out of physical mem
JMP AUPTDone
AUPT01:
CALL GetCrntJobNum ;Leaves job num in EAX (for LinToPhy)
MOV EBX, pNextPT ;Pre allocated Page (Linear Address)
CALL LinToPhy ;EAX will have Physical address
; Put it in the User PD (and linear in shadow).
; Find first empty slot
CALL GetpCrntJCB ;pJCB in EAX
MOV EDI, JcbPD ;Offset to PcbPD in JCB
ADD EDI, EAX ;EDI points to UserPD Address
MOV ESI, [EDI] ;ESI now points to PD
ADD ESI, 2048 ;ESI now points to upper 1 GB in PD
MOV ECX, 511 ;Number of entries (at least 1 is already gone)
AUPT02:
ADD ESI, 4 ; Next possible empty entry
MOV EBX, [ESI]
OR EBX, EBX ; Is it empty?
LOOPNZ AUPT02 ; No! (Try again)
; ESI now points to empty Slot
; Physical Address of new table is still in EAX
; Get Linear address back into EBX
; and put them into PD
OR EAX, MEMUSERD ;Set user bits (Read/Write)
MOV [ESI], EAX ;Physical address in lower half
ADD ESI, 2048 ;Move to shadow
MOV EBX, pNextPT ;Linear add back into EBX
MOV [ESI], EBX ;Put in Linear address of PT (upper half)
;Now we now need another PreAllocated Page Table for
;next time. Get a run of 1 for next new page table
MOV EBX, 1 ;size of request
XOR EAX, EAX ;PD shadow offset needed by FindRun (0)
CALL FindRun
OR EAX, EAX ;was there an error (0 means no mem)
JNZ AUPT05
MOV EAX, ErcNoMem ;
JMP SHORT AUPTDone
AUPT05:
MOV pNextPT, EAX ;save pNextPT (the linear address)
CALL AddRun ;AddRun will return NON-ZERO on error
AUPTDone:
POP EDI ;
POP ESI ;
POP EDX ;
POP ECX ;
POP EBX ;
RETN
;=============================================================================
; AddOSPT
; This creates a new OS Page Table, initializes it and sticks it
; in the OS's PD (in OS address space below 1GB).
; This also updates ALL PDs for ALL jobs. We must do this
; to ensure the OS code can reach its memory no matter what JOB/TASK
; it is running in.
;
; IN : Nothing
; OUT: 0 if OK or Error (ErcNoMem - no free phy pages!)
; USED: EAX, EFlags
;
AddOSPT:
PUSH EBX ;(save for caller)
PUSH ECX ;
PUSH EDX ;
PUSH ESI ;
PUSH EDI ;
MOV EAX, _nPagesFree ;See if have enuf physical memory
OR EAX, EAX
JNZ AOPT01
MOV EAX, ErcNoMem ;Sorry, out of physical mem
JMP AOPTDone
AOPT01:
MOV EAX, 1 ;OS Job Number (Monitor)
MOV EBX, pNextPT ;Pre allocated Page (Linear Address)
CALL LinToPhy ;EAX will have Physical address
; Put it in the OS PD (and linear in shadow).
; Find first empty slot
MOV ESI, OFFSET PDir1 ; ESI points to OS Pdir
MOV ECX, 511 ; Count of PDEs to check
AOPT02:
ADD ESI, 4 ; Next possible empty entry
MOV EBX, [ESI]
OR EBX, EBX ; Is it empty?
LOOPNZ AOPT02 ; No! (Try again)
; ESI now points to empty PDir Slot
; EAX still has Physical Address of new table
; Get Physical Address back into EBX
; and put them into PDir
OR EAX, PRSNTBIT ;Set present bit
MOV [ESI], EAX ;Physical address in lower half
ADD ESI, 2048 ;Move to shadow
MOV EBX, pNextPT ;Linear add back into EBX
MOV [ESI], EBX ;Put in Linear address of PT (upper half)
; Update ALL PDs from PDir1 !!
; This doesn't happen often if it happens at all.
; The OS will usually not take 4 MBs even with ALL
; of its dynamic structures (except on
; a 32 Mb system or larger and when fully loaded)
MOV EDX, nJCBs ; # of dynamic JCBs
AOPT03:
MOV EAX, EDX ;Next JCB
CALL GetpJCB ;EAX now has pointer to a job's PD
MOV ECX, [EAX.JcbPD] ;See if PD id zero (Inactive JCB)
OR ECX, ECX ;Is it a valid Job? (0 if not)
JZ AOPT04 ;No, Not a valid JCB (unused)
ADD EAX, JcbPD ;EAX NOW points to PD of JCB
MOV EBX, OFFSET PDir1 ;Source of Copy
PUSH EDX ;Save nJCB we are on
PUSH EAX ;Save values on stack
PUSH EBX
PUSH EBX ;Source
PUSH EAX ;Destination
PUSH 1024 ;Lower half of PD (Physical Adds)
CALL FAR PTR _CopyData
POP EBX ;Get values from stack
POP EAX
ADD EBX, 2048 ;Move to shadow
PUSH EBX
ADD EAX, 2048 ;Move to shadow
PUSH EAX
PUSH 1024 ;Upper half of PD (Linear Adds)
CALL FAR PTR _CopyData
POP EDX ; Get back JCB number
AOPT04:
DEC EDX
CMP EDX, 2
JA AOPT03 ;Jobs 1 & 2 use PDir1 (Mon & Debugger)
;At this point the new table is valid to ALL jobs!
;We now need another PreAllocated Page Table for
;next time. Get a run of 1 for next new page table
MOV EBX, 1 ;size of request
XOR EAX, EAX ;PD shadow offset needed by FindRun (0)
CALL FindRun
OR EAX, EAX ;was there an error (0 means no mem)
JNZ AOPT05
MOV EAX, ErcNoMem ;
JMP SHORT AOPTDone
AOPT05:
MOV pNextPT, EAX ;save pNextPT (the linear address)
CALL AddRun ;AddRun
XOR EAX, EAX ;Set ErcOK (0)
AOPTDone:
POP EDI ;
POP ESI ;
POP EDX ;
POP ECX ;
POP EBX ;
RETN
;=============================================================================
; GetGDTDesc
; You supply the GDT selector in BX and this puts entry in EAX,EDX.
; EAX, EBX and EDX are used.
; This assumes that the PUBLIC Variable GDTbase has been filled in by
; the OS using SGDT after it went PMode.
; Used by the Debugger among other things...
;
GetGDTDesc:
AND EBX,0000FFF8h ;Mask any left overs (hi word)
ADD EBX,GDTBase ;Add to GDT base
MOV EAX,[EBX]
MOV EDX,[EBX+4]
RETN
;=============================================================================
;=============================================================================
; BEGIN PUBLIC CALL DEFINITION FOR MEMORY MANAGEMENT
;=============================================================================
;=============================================================================
; PUBLIC calls (far through call gates)
; AddCallGate - Adds a public CallGate to the GDT
; AddIDTGate - Adds an Interrupt Vector to the IDT
; AllocPage - Returns a ptr for allocated memory pages (Hi Phys)
; AllocOSPage - Returns a ptr with linear memory pages
; AllocDMAPage - Returns a ptr with physical and linear memory pages
; AliasMem - Aliases a memory address from one Job to another
; DeAllocPage - Provided with ptr, deallocates memory pages
; QueryMemPages - Tells you how many pages are left free
; GetPhyAdd - Returns the Physical Address for a Linear Address
;=============================================================================
; AddGDTCallGate will build and add a GDT entry for a call gate allowing
; access to OS procedures. This call doesn't check to see if the GDT
; descriptor for the call is already defined. It assumes you know what you
; are doing and overwrites one if already defined. The Selector number is
; checked to make sure you're in range (40h thru max call gate num).
;
; IN: AX - Word with Call Gate ID type as follows:
;
; DPL entry of 3 EC0x (most likely)
; DPL entry of 2 CC0x (Not used in MMURTL)
; DPL entry of 1 AC0x (Not used in MMURTL)
; DPL entry of 0 8C0x (OS call ONLY)
; (x = count of DWord params 0-F)
;
; CX Selector number for call gate in GDT (constants!)
; ESI Offset of entry point in segment of code to execute
;
; OUT: EAX Returns Errors, else 0 if all's well
;
; USES: EAX, EBX, ECX, ESI, EFLAGS
_AddCallGate PROC FAR
CMP CX, 40h ;Is number within range of callgates?
JAE AddCG01 ;not too low...
MOV EAX, ercBadGateNum
RETF
AddCG01:
MOVZX EBX, CX
SUB EBX, 40 ;sub call gate base selector
SHR EBX, 3 ;make index vice selector
CMP EBX, nCallGates ;see if too high!
JBE AddCG02 ;No...
MOV EAX, ercBadGateNum ;Yes...
RETF
AddCG02:
MOVZX EBX, CX ;Extend selector into EBX
ADD EBX, GDTBase ;NOW a true offset in GDT
MOV WORD PTR [EBX+02], 8 ;Put Code Seg selector into Call gate
MOV [EBX], SI ;0:15 of call offset
SHR ESI, 16 ;move upper 16 of offset into SI
MOV [EBX+06], SI ;16:31 of call offset
MOV [EBX+04], AX ;call DPL & ndParams
XOR EAX, EAX ;0 = No Error
RETF
_AddCallGate ENDP
;=============================================================================
; AddIDTGate will build and add an IDT Trap, Interrupt, or Task Gate.
; The Selector of the call is Always 8 for Int or Trap, and is the
; TSS of the task for a Task gate.
;
; IN: AX - Word with Gate ID type as follows:
; Trap Gate with DPL of 3 8F00
; Interrupt Gate with DPL of 3 8E00
; Task Gate with DPL of 3 8500
;
; BX - Selector of gate (08 or TSS selector for task gates)
;
; CX - Word with Interrupt Number (00-FF)
;
; ESI - Offset of entry point in OS code to execute
; (THIS MUST BE 0 FOR TASK GATES)
;
; USES: EAX, EBX, ECX, EDX, ESI, EFLAGS
_AddIDTGate PROC FAR
MOVZX EDX, CX ;Extend INT Num into EDX
SHL EDX, 3 ;Gates are 8 bytes each (times 8)
ADD EDX, OFFSET IDT ;EDX now points to gate
MOV WORD PTR [EDX+4], AX ;Put Gate ID into gate
MOV EAX, ESI
MOV WORD PTR [EDX], AX ;Put Offset 15:00 into gate
SHR EAX, 16
MOV WORD PTR [EDX+6], AX ;Put Offset 31:16 into gate
MOV WORD PTR [EDX+2], BX ;Put in the selector
RETF
_AddIDTGate ENDP
;
;
;=============================================================================
; AllocOSPage --
; This allocates one or more pages of physical memory and returns a
; linear pointer to one or more pages of contiguous memory in the OS space.
; A result code is returned in the EAX register.
; STEPS:
; 1) See if we have enough physical memory (check nPagesFree)
; 2) Find a contiguous run of linear pages to allocate (PTEs)
; 3) Allocate each physical page placing it in the run of PTEs
;
; We search thru the page tables for the current job and find enough
; contiguous PTEs to satisfy the request. If the current PT doesn't have
; enough contiguous entries, we add another page table to the OS PD
; and get them from the new one and the old one (i.e., the run may
; span page tables).
;
; Procedureal Interface :
;
; AllocOSPage(dn4KPages,ppMemRet): dError
;
; dn4KPages is a DWORD (4 BYTES). This is the number of contigous pages
; to be allocated.
;
; ppMemRet points to the pointer where the address of the
; new linear memory is returned.
;
n4KPages EQU [EBP+10h] ;These equates are also used by AllocPage
ppMemRet EQU [EBP+0Ch] ;
_AllocOSPage PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
PUSH MemExch ;Wait at the MemExch for Msg
MOV EAX, pRunTSS ;Put Msg in callers TSS Message Area
ADD EAX, TSS_Msg
PUSH EAX
CALL FAR PTR _WaitMsg
CMP EAX,0h ;Kernel Error??
JNE SHORT ALOSPExit ;Yes! Serious problem...
MOV EAX,n4KPages ;size of request
OR EAX,EAX ;More than 0?
JNZ ALOSP00 ;Yes
MOV EAX,ercBadMemReq ;Can't be zero!
JMP ALOSPExit ;
ALOSP00:
CMP EAX, _nPagesFree ;See if have enuf physical memory
JBE ALOSP01 ;Yes
MOV EAX, ErcNoMem ;Sorry boss, we're maxed out
JMP SHORT ALOSPExit
ALOSP01:
MOV EBX,n4KPages ;size of request
XOR EAX, EAX ;PD shadow offset needed by FindRun (0)
CALL FindRun
OR EAX, EAX ;(0 = No Runs big enuf)
JNZ SHORT ALOSP02 ;No Error!
;If we didn't find a run big enuf we add a page table
CALL AddOSPT ;Add a new page table (we need it!)
OR EAX, EAX ;See if it's 0 (0 = NO Error)
JZ SHORT ALOSP01 ;Go back & try again
JMP SHORT ALOSPExit ;ERROR!!
ALOSP02:
;EAX now has linear address
;EBX still has count of pages
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -