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

📄 flatmem.inc

📁 在DOS下访问4G以上的内存的方法. 有详细的例子说明
💻 INC
字号:
;----------------------------------------------------------------------------
;                      MASSiVE Flat Real mode routines
;                               (Version 1.0B)
;                                    by
;                               NiX/MASSiVE
;                            Butterfly/MASSiVE
;
; You may use this sourcecode for free, we don't accept anything in return.
; But we would really like it if you greet us, or send your newest productions
; to us.
;
; This is a beta version, only providing you with the essential routines and
; some examples, just real plain flat-real-mode. More special things will be
; available in a next version.
;
; Read the DOC for more information.

.386P    ; 386 Code ofcourse...

;---------------------------------------------------------------------------
; Descriptors and stuff used for setting up FRM
mem32_GDT       dw      4 dup(0)

Code16GDT = 8
                dw      0ffffh,0ffh,9a00h,0
Data16GDT = 16
                dw      0ffffh,0ffh,9200h,0
Data32GDT = 24  
                dw      0ffffh,0ffh,9200h,8fh

GDTptr label fword
                dw      offset GDTptr-1-offset Mem32_GDT
                dd      offset Mem32_GDT ; Absolute adress GDTtable
                dw      0

;-------------------------------------------------------------------------
; This routine sets DS, ES, FS and GS to a 4Gigabyte limit.
; To do this it swaps to PM for a little while, this is not possible in V86
; mode. If computer is in V86 mode the carry will be set on return, and you
; are still in RM.
; Crashes segment registers!!!

Set4Gig:        mov     eax,cr0   ; Check for V86 mode
                ror     eax,1     ;
                jc      Leave4Gig ; If carry set get out of here.

                mov     ax,cs     ; Set up GDT for this code segment
                mov     ds,ax
                movzx   eax,ax
                shl     eax,4
                add     dword ptr ds:GDTptr+2,eax
                lgdt    fword ptr ds:GDTptr

                mov     ax,cs
                and     eax,65535
                shl     eax,4
                mov     word ptr ds:Mem32_GDT[Code16GDT+2],ax
                mov     word ptr ds:Mem32_GDT[Data16GDT+2],ax
                ror     eax,16
                mov     byte ptr ds:Mem32_GDT[Code16GDT+4],al
                mov     byte ptr ds:Mem32_GDT[Data16GDT+4],al
                mov     byte ptr ds:Mem32_GDT[Code16GDT+7],ah
                mov     byte ptr ds:Mem32_GDT[Data16GDT+7],ah

                cli    ; No ints

; Beam us to PMODE!!
                mov     eax,cr0
                or      al,1
                mov     cr0,eax

                db      0eah               ; Far jump to PMODE label
                dw      offset Pmode
                dw      Code16GDT

; We're in PMODE!!
Pmode:          mov     ax,Data32GDT
                mov     ds,ax  ; Set them all to 4Gig
                mov     es,ax
                mov     fs,ax
                mov     gs,ax
                
; Beaming out!
                mov     eax,cr0
                and     al,0feh
                mov     cr0,eax

                db      0eah           ; Far jump to Rmode label.
                dw      offset Rmode
                dw      Code

; Back in the real world!
Rmode:          clc  ; No carry, everything went OK

                sti  ; Ints Back on.
                
Leave4Gig:      ret

;----------------------------------------------------------------------------
; Initialises HIMEM.SYS for our program. If HIMEM.SYS isn't present a carry
; will be returned.
; This routine must be called before you use all other routines except for
; SET4GIG
Himem_Init:     mov     ax, 4300h
                int     2Fh
                cmp     al, 80h
                je      HImemfound
                stc
                ret
Himemfound:
                push    es
                mov     ax, 4310h
                int     2Fh
                mov     [word ptr cs:Himem_Entry], bx
                mov     [word ptr cs:Himem_Entry+2], es
                pop     es
                clc
                ret

Himem_Entry     dd      ?

;-----------------------------------------------------------------------------
; Allocates XMS memory
; Input:        DX = Size in KB
; Output:       DX = Handle
;               If carry set alloc failed (probably out of mem...)
Alloc_XMS:      mov     ah, 9
                call    [cs:Himem_Entry]
                cmp     dx,ax
                jnz     AllocOK
                or      ax,ax
                jnz     AllocOK
                stc
                ret
AllocOK:        clc
                ret

;-----------------------------------------------------------------------------
; Deallocates XMS memory
; Input:        DX = Handle
DAlloc_XMS:     push    dx
                mov     ah, 0dh
                call    [cs:Himem_entry]
                pop     dx
                mov     ah, 0Ah
                call    [cs:Himem_Entry]   ; DAlloc
                ret
               

;-----------------------------------------------------------------------------
; Returns absolute 32-bit adress of an XMS-Memoryblock
; Input:        DX = Handle
; Output:       EDX = 32Bit start adress of memoryblock
GetLinearAddress:
                mov     ah, 0Ch
                call    [cs:Himem_Entry]
                shl     edx,16
                mov     dx,bx
                ret


;-----------------------------------------------------------------------------
; Returns the largest available XMS-Memoryblock
; Output:       DX = Size of largest available memoryblock
GetMax_XMS:     mov     ah, 8
                call    [cs:Himem_Entry]   ; avail.
                ret
               
;-----------------------------------------------------------------------------
; Enables the A20 adress line. This is needed to adress the memory above 1Mb.
; Do this at the start of your program and everytime another program has been
; active. In an interrupt routine this means you should do it everytime the
; routine is being called, don't worry, it doesn't takes much time.
EnableA20:
                mov     al,0D1h
                out     64h, al
                call    A20wait
                mov     al,0DFh
                out     60h, al
                call    A20wait
                mov     al,0FFh
                out     64h,al
                call    A20wait
                ret

A20Wait:        in      al,64h
                jmp     $+2
                and     al,2
                jnz     A20wait
                ret


⌨️ 快捷键说明

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