📄 header.a86
字号:
; DX = current PSP
; ES:SI -> new CS:IP
; CX:DI -> users stack
; On Exit:
; AX = FCB validity flags
; BX = 0
; SS:SP = users stack
; CS:IP = values from EXE header
; DS = ES = DX = current PSP
;
; When we start execing the application we have the A20 gate disabled so
; buggy EXE packed programs will unpack properly.
; We also hook Int 21 and Int 2F to re-enable the A20 gate on the first
; calls made to them. (These should only happen AFTER the unpacking).
;
call A20Disable
mov ss,cx ; switch to new USER stack
mov sp,di
push es
push si ; CS:IP on USER stack
mov ds,dx ; DS = ES = PSP we are exec'ing
mov es,dx
xor bx,bx ; BX = zero, set flags
sti
retf ; lets go!
Func4B05Stub:
;============
; On Entry:
; ES:BP -> callers stack
; DX = PSP to exec on
; On Exit:
; callers registers restored
;
call A20Disable ; turn off A20
mov ax,es
mov ss,ax ; back to users stack
mov sp,bp
POP$DOS ; Restore Registers
iret
Public int2FNext, int2FBiosHandler
Int2FBios:
;---------
; On Entry:
; DS on stack
; On Exit:
; All regs preserved
;
; Pass on an Int 2F call to the BIOS
pop ds ; recover DS and pass on to BIOS
db 0EAh ; JMPF bios Int 2F entry point
int2FBiosHandler dw 0,0 ; filled in at run time
int2FNext dw Int2FBios, 0 ; seg filled in at run time
nul_strat:
cmp RH_CMD,CMD_INPUT
jne nul_strat10 ; if it's input
mov RH4_COUNT,0 ; Say none transferred #IJ
nul_strat10:
mov RH_STATUS,RHS_DONE ; Set the DONE bit in the
nul_int: ; Request Header and Return
clc ; (indicate success for SHARE)
retf
Public invalid_stub
invalid_stub:
mov ax,ED_FUNCTION ; indicate bad function
fdos_stub_entry:
stc ; indicate error
retf
Public lock_bios, unlock_bios, lock_tables, unlock_tables
lockbios:
;--------
push ax
mov ax,8002h
jmps CriticalSection
unlockbios:
;----------
push ax
mov ax,8102h
jmps CriticalSection
locktables:
;----------
push ax
mov ax,8001h
jmps CriticalSection
unlocktables:
;------------
push ax
mov ax,8101h
; jmps CriticalSection
CriticalSection:
;---------------
; On Entry:
; AX = critical section number
; STACK = original AX
; On Exit:
; AX poped from stack
;
cmp cs:criticalSectionEnable,0
je CriticalSection10
int 2ah ; issue critical section callout
CriticalSection10:
pop ax
retf
public criticalSectionEnable
criticalSectionEnable db 0
Public SwStartupInfo
SwStartupInfo dw 3 ; version
dw 0
dw 0 ; link to next in chain
;; dw offset vxdName ; Virtual Dev file
;; replaced above line with DW 0 as vxd no longer required BAP
dw 0
dw 0
dw 0,0 ; Reference Data
dw offset instanceItems
instanceSeg dw 0
;vxdName db 'A:\OPENDOS.386',0
public histbuf1, histsiz1, histbuf2, histsiz2
instanceItems:
dw 0 ; offset zero (for instancing)
histbuf1 dw 0 ; Command history buffer segment
histsiz1 dw 0 ; size (in bytes)
dw 0 ; offset zero (for instancing)
histbuf2 dw 0 ; Application history buffer segment
histsiz2 dw 0 ; size (in bytes)
; some ROS fixups
dw 000h,050h,002h ; BASIC variables
dw 00Eh,050h,014h ; BASIC variables
; some BIOS fixups
dw 0B8h,070h,004h ; BIOS req_hdr
; dw 16Ch,070h,002h ; BIOS dev_no (no longer required)
dw 600h,070h,002h ; BIOS local_char
bdosInstanceFixups rw 0
dw con_device,0,4 ; CON: device ptr
dw savbuf,0,column-savbuf+1
dw dmd_upper_root,0,2
dw dmd_upper_link,0,1
dw exe_buffer,0,EXE_LENGTH
dw 0,0 ; zero terminated instance list
xmsDriver rd 1
globalPrivateData:
rd 1 ; 0000 delwatch driver vector
rw 4 ; space for expansion
;** COUNTRY INFO **
;
; The following routines are called by the end user using the DWORD
; pointers in the Country Data. Each Country Data area contains a
; pointer to one of the following routines. All valid charcater
; codes above 7Fh are translated to Upper Case
;
Public xlat_xlat
xlat_xlat:
cmp al,080h
jb xlat_exit
sub al,080h
push bx
mov bx,offset Standard_table
xlat cs:al
pop bx
xlat_exit:
retf
Public cur_country
Public cur_cp
Public default_country
Public country_data
Public Ucasetbl
Public FileUcasetbl
Public FileCharstbl
Public Collatingtbl
Public DBCS_tbl
Public info1_len
Public info2_len
Public info4_len
Public info5_len
Public info6_len
Public info7_len
Public intl_xlat
; table of pointers to default country info. pointed to in BDOS header
Public NoYesChars
NoYesChars db 'NnYy'
dw country_data
dw default_country
dw Ucasetbl
dw FileUcasetbl
dw FileCharstbl
dw Collatingtbl
dw DBCS_tbl
org 11F0h - PCMODE_CODE_START
dummy_fcbs dw 0ffffh ; terminate now
dw 0
dw 1 ; with one entry
rb DHNDL_LEN ; this many bytes in it
org 1232h - PCMODE_CODE_START
Public country_filename
country_filename db '\COUNTRY.SYS'
rb 64 - length country_filename
org 1276h - PCMODE_CODE_START
; We fix the country tables at this location for the benefit of
; LAN Manager 2.2 extended edition. It peeks directly rather than use
; int 21/65 !
countryTable:
db 2
dw offset UCasetbl,0
db 4
dw offset FileUCasetbl,0
db 5
dw offset FileCharstbl,0
db 6
dw offset Collatingtbl,0
db 7
dw DBCS_tbl,0
db 1
dw 26h
country_data:
cur_country dw 1 ; Country Code
cur_cp dw 437 ; Code Page
default_country:
dw US_DATE ; Date Format (Binary)
db '$',0,0,0,0 ; Currency Symbol
db ',',0 ; Thousands Separator
db '.',0 ; Decimal Separator
db '-',0 ; Date Separator
db ':',0 ; Time Separator
db 0 ; Symbol before Value without Space ($n.nn)
db 2 ; Significant Currency Digits
db CLOCK_12 ; Time Format
intl_xlat dw xlat_xlat ; Case Translation Routine
dw 0000h ; Case Translation Segment (Runtime Fixup)
db ',',0 ; Data List Separator
info1_len equ word ptr (offset $ - offset country_data)
; If NOT COUNTRY.SYS then include the
rb 10 ; 10 zero bytes held at the end of the
; country information.
PCM_CODEND CSEG PARA
Public code_end
code_end rb 0
BDOS_DATA DSEG
Public hashroot, hashmax
; The hashroot must be global, but we also need to make it accessible
; during CONFIG so we copy it from the private data area
hashroot dw 0,0
PCM_HISTORY CSEG
patch_area dw 0666h
include i:patch.cod
PCM_ICODE cseg
;
; The following routine initializes all the standard MS-DOS interrupt
; vectors which are initialized to point to the PC-MODE handlers.
;
; Entry: AX Memory Size - Paragraphs
; BX First Available Paragraph
; DL Initial Drive
; DS PCM Dseg
;
pcmode_init:
and cs:patch_version,not DOSINROM
; won't clear if we are in ROM...
mov cs:pcmode_dseg,ds ; save PCM Dseg
mov ds:instanceSeg,ds ; fixup pointer to instance items
; removed this as VxD no longer required BAP
; mov ds:vxdNameSeg,ds ; and vxdName
; add ds:vxdName,dl ; fixup drive letter
mov ds:word ptr buf_ptr+2,ds
mov ds:word ptr file_ptr+2,ds
mov ds:word ptr fcb_ptr+2,ds
push ax ; Save the memory size
push bx ; First Free Paragraph
mov ds:current_dsk,dl ; save initial drive
inc dl ; make drive one based
mov ds:bootDrv,dl ; and save for func 3305
mov ax,ds ; AX = PCMode Data
mov ds:word ptr fdos_stub+WORD,ax
add ds:dummy_sysdat,ax ; point dummy "sysdat" at a zero word
; ie. dummy "secure path" segment
mov si,offset countryTable
countryFixupLoop:
mov ds:word ptr 3[si],ds ; fixup the segment
add si,5 ; onto the next entry
cmp ds:word ptr 3[si],0 ; done the lot yet ?
je countryFixupLoop
mov es,ax ; ES -> PCMode Data
mov di,offset stub_entries ; ES:DI -> stub segs
mov cx,NUM_STUB_ENTRIES ; entries to initialise
stubs_loop:
add di,WORD ; skip the offset
stosw ; fixup segment
loop stubs_loop ; do the next one
mov di,offset share_stub ; fixup the SHARE entries
mov cx,NUM_SHARE_STUB_ENTRIES
share_loop:
add di,WORD ; skip the offset
stosw ; fixup segment
loop share_loop
; mov cx,0
mov es,cx ; Initialize the DOS vectors
mov ax,es:.INT2F_OFFSET ; remember address of BIOS Int 2F
mov ds:int2FBiosHandler,ax
mov ax,es:.INT2F_SEGMENT
mov ds:int2FBiosHandler+2,ax
mov ds:int2FNext+2,ds ; fixup seg of out stub
mov cx,40h-2Ah ; 2A-3F point at IRET in DOS Data Seg
mov di,INT2A_OFFSET
dummy_vecs_loop:
mov ax,offset DummyIRET ; point at an IRET
stosw ; do the offset
mov ax,ds
stosw ; then the segment
loop dummy_vecs_loop
mov si,offset def_data_vecs ; the following vector point to
mov cx,no_def_data_vecs ; pcmode DATA seg
def_data_vecs_loop:
lods cs:ax ! mov di,ax ; Get the Vector Offset (from CS)
db 2Eh ; CS:
movsw ; copy service routine offset
mov ax,ds ; finally fixup the segment too
stosw
loop def_data_vecs_loop
mov es:byte ptr .INT30_OFFSET,0EAh
; fixup CALL 5 JMPF
mov si,offset bdosInstanceFixups
InstanceFixupLoop:
mov ds:2[si],ds ; fixup data segment
add si,6 ; onto next item
mov ax,ds:[si] ; still BDOS ?
or ax,ds:2[si]
jnz InstanceFixupLoop ; yep, do another one
push cs ; we will have a RETF
call pcmode_reinit ; to return from this call
pop ax ; First Free Paragraph
pop dx ; Restore the BIOS memory size
sub dx,ax ; convert to TPA size
dec dx ; Decrement the Size by DMD Size
push ax
add ax,dx ; AX = possible next DMD
mov es,ax
mov al,IDZ ; assume no extra DMD's
cmp al,es:DMD_ID ; have we extra one ?
jne pcmode_init10
mov al,IDM ; yes, no longer end of chain
dec dx ; decrement by size of existing DMD
pcmode_init10:
pop es
mov es:DMD_ID,al ; Last DMD in list
mov es:DMD_PSP,0000h ; This is Free Memory Owning PSP == 0
mov es:DMD_LEN,dx ; Save Memory Length
mov es:word ptr DMD_NAME,'S'+256*'D'
mov es:DMD_NAME+2,0
mov ds:dmd_root,es ; Save the DMD address in root
retf
eject
;
;
; On Entry:
; DS = DOS data seg
pcmode_reinit:
;=============
mov ds:word ptr intl_xlat+2,ds
; fixup intl case routine
mov ds:codeSeg,cs ; fixup code segment
mov ax,ds:hashptr ; make a copy of the hashroot
mov ds:hashroot,ax ; so it's global
mov ax,ds:hashptr+WORD
mov ds:hashroot+WORD,ax
mov al,ds:@hist_flg ; get initial history flags
and ax,RLF_ENHANCED+RLF_INS+RLF_SEARCH
mov ds:cle_state,ax ; use to set initial editing state
mov ds:word ptr xmsDriver,offset invalid_stub
mov ds:word ptr xmsDriver+2,ds
mov bx,offset FirstCodeEntryPoint
pcmode_reinit10:
mov ds:3[bx],cs ; fixup segment of the JMPF
add bx,8 ; onto the next one
cmp bx,offset LastCodeEntryPoint
jb pcmode_reinit10
mov ax,ds:hmaRoot ; have we established an HMA free chain
or ax,ds:hmaAlloc ; or have any registered users ?
jz pcmode_reinit30 ; if so hook for EXEPACK support
mov ax,4300h
int 2Fh ; do we have an XMS driver ?
cmp al,80h ; 80h says yes
jne pcmode_reinit30
mov ax,4310h ; get it's entry point
int 2Fh ; in ES:BX
mov ds:word ptr xmsDriver,bx
mov ds:word ptr xmsDriver+2,es
mov ax,0FFFFh
mov es,ax
inc ax ; AX = 0
mov es:.94h,ax ; zero the HMA alias for Int 21
mov es:.96h,ax ; we use this as our A20 gate test
mov bx,offset FirstCodeEntryPoint
pcmode_reinit20:
mov ax,offset A20Enable-3 ; we need a relative offset to
sub ax,bx ; poke in a "call A20Enable"
xchg ax,ds:1[bx] ; pick up the entry point segment
mov ds:byte ptr 0[bx],0E8h ; CALL NEAR
mov ds:byte ptr 3[bx],0EAh ; JMPF
mov ds:4[bx],ax ; fixup the offset
mov ds:6[bx],cs ; fixup the segment
add bx,8 ; ready to do the next entry
cmp bx,offset LastCodeEntryPoint
jb pcmode_reinit20
mov ax,70h ; now fixup the BIOS A20 Enable
mov es,ax
xor di,di ; patch entry point at 70:0
mov al,09Ah ; CALLF
stosb
mov ax,offset BIOSA20Enable
stosw ; offset
mov ax,ds
stosw ; seg
mov al,0C3h
stosb ; RET
cmp ds:codeSeg,0F000h ; have we relocated DOS into the HMA ?
jb pcmode_reinit30 ; if so we must remember it
or cs:patch_version,DOSINHMA
pcmode_reinit30:
retf
def_data_vecs rw 0
dw INT22_OFFSET, DummyIRET
dw INT23_OFFSET, DummyIRET
dw INT24_OFFSET, Int24Entry
dw INT28_OFFSET, DummyIRET
dw INT20_OFFSET, Int20Entry
dw INT21_OFFSET, Int21Entry
dw INT25_OFFSET, Int25Entry
dw INT26_OFFSET, Int26Entry
dw INT27_OFFSET, Int27Entry
dw INT2F_OFFSET, Int2FEntry
dw INT30_OFFSET+1,Call5Entry
no_def_data_vecs equ (offset $ - offset def_data_vecs)/4
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -