📄 ldseg.asm
字号:
;*
;* COW : Character Oriented Windows
;*
;* ldseg.asm : segment loader
.xlist
include kernel.inc
include galloc.inc
include rlb.inc ;* relocation info
.list
IFDEF DEBPUB
PUBLIC OpenSwapFile
ENDIF
sBegin DATA
assumes DS,DGROUP
externW <psLom>
externW <fColorModeOld> ;* last color mode
IFNDEF NOPCODE
externW fNew ;* from interpreter
ENDIF ;!NOPCODE
sEnd DATA
sBegin BSS
assumes DS,DGROUP
globalB iexeCur, 0 ;* current .EXE file open
;* loader only uses the first file
;* set to 255 if closing file
globalW fFreeOpen, 0 ;* TRUE => 1 free open (no warning)
;* (i.e. don't prompt before opening file)
sEnd BSS
externFPublic <PromptSwapDisk> ;* from App or stub.
externFP <GlobalReAlloc, GlobalHandle>
externFPublic <FInitScreenInternal>
externFPublic <ExitKernel> ;* from kerninit.asm
;* in CORE segment (USER screen)
IFDEF KEEP_SYMDEB_CODE
externFP <DebugDefineSegment>
ENDIF ; KEEP_SYMDEB_CODE
;*****************************************************************************
sBegin KERNEL
assumes CS,KERNEL
assumes SS,DATA
assumes DS,NOTHING ;* Called by Reload Segment !
externNP <FRelocSegment> ;* from ldreloc.asm
externNP <PatchThunkLoaded> ;* from ldthunk.asm
externNP <PatchStackLoaded> ;* from ldstack.asm
;********** LoadSegment **********
;* entry : segno = segment to load
;* * Load in the segment & relocate
;* exit : ax = ps of loaded segment
cProc LoadSegment,<NEAR,PUBLIC>,<si,di>
parmW segno
localW psDest ;* destination ps
cBegin LoadSegment
mov fFreeOpen,sp ;* allow 1 free open
;* * calculate the pnewseg1
mov es,psLom
Assert <SIZE NEW_SEG1 EQ 10>
mov si,segno
AssertReset si,0ff00h ;* must be byte
AssertSet si,000ffh ;* must be non-zero
dec si ;* zero base for calculation
shl si,1
mov ax,si
shl si,1
shl si,1
add si,ax ;* times 10
add si,es:[neLom.ne_segtab] ;* ES:SI => NEW_EXE1
;* * Segment MUST be MOVEABLE CODE
AssertSet es:[si].ns_flags,NSMOVE
AssertReset es:[si].ns_flags,NSDATA
;* * Allocate enough space to read in
xor ax,ax
cCall GlobalReAlloc,<es:[si].ns_handle,ax,es:[si].ns_minalloc,ax>
;* * Abort if error
or ax,ax
jnz lds_ReAllocOK
BREAKPOINT
mov ax,255
cCall ExitKernel,<ax> ;* Fatal error
lds_reAllocOK:
AssertNe ax,0
cCall GlobalHandle,<ax> ;* return dx = ps
;* * save where loaded
mov psDest,dx ;* ps where loaded
;* * Stuff in the correct flags
dec dx ;* point to arena
mov es,dx ;* es:0 => arena
mov es:[ga_flags],GA_MOVEABLE OR GA_DISCCODE
assumes DS,NOTHING ;!!!
push ds ;* random DS
mov ds,psLom
;* * Make sure we have the correct file open
IFDEF DUAL
loads_retry:
mov di,lomOffset neLom
mov ax,segno
cCall GetRle
mov ah,ds:[bx].re_iexe
cmp ah,iexeCur
je correct_file_open
Save <bx>
cCall OpenSwapFile
jmp short load_rlb
correct_file_open:
cmp bx,ds:[pbRleCurLom]
je correct_rlb_loaded
load_rlb:
Save <bx>
cCall LoadRle
correct_rlb_loaded:
ELSE ;!DUAL
mov ax,ds:[si].ns_flags
Assert <SHIFTDPL EQ 10>
and ah,HIGH(NSDPL)
shr ah,1
shr ah,1
and ah,3 ;* iexe
cmp ah,iexeCur
je correct_file_open
loads_retry:
cCall OpenSwapFile
correct_file_open:
ENDIF ;!DUAL
;* * Seek to the proper position in the file
mov dx,ds:[si].ns_sector ;* "sector"
xor ax,ax ;* ax:dx used for sector
mov cx,ds:[neLom.ne_align] ;* shift left count
loads_lp1:
shl dx,1
rcl ax,1
loop loads_lp1
mov cx,ax ;* cx:dx = lfa
IFDEF DUAL
IFDEF DEBUG
AssertEQ bx,ds:[pbRleCurLom]
ENDIF ;DEBUG
sub dx,ds:[bx].LO_re_dlfaBias ;* adjust lfa
sbb cx,ds:[bx].HI_re_dlfaBias
ENDIF ;DUAL
mov bx,ds:[fdExeLom]
mov ax,4200h ;* seek device, from start
int 21h
jc loads_error ;* seek error ?
;* * Read it all in (bx = fd)
mov cx,ds:[si].ns_cbseg ;* file length
push ds
mov ds,psDest ;* where to load
xor dx,dx ;* ds:dx = ds:0 = read address
mov ah,3fh ;* read from device
int 21h
pop ds
jc loads_error ;* read error ?
cmp ax,cx
jne loads_error ;* read them all ?
;* * Test to see if we must zero fill the end of the memory block
mov di,ds:[si].ns_cbseg ;* offset past end
mov cx,ds:[si].ns_minalloc ;* may be larger
sub cx,di
jcxz loads_end
cld
mov es,psDest
xor al,al
rep stosb ;* erase it
loads_end: ;* all loaded
cCall FRelocSegment,<si, psDest, segno> ;* relocate it, DS == psLom !
or ax,ax
jz loads_error
pop ds ;* restore original DS
;* * Fix up thunks etc
cCall PatchThunkLoaded,<segno, psDest>
;* * Fix up stack
cCall PatchStackLoaded,<segno, psDest>
;* * Optional inform debugger
IFDEF KEEP_SYMDEB_CODE
mov cx,segno
dec cx ;* zero based seg #
xor ax,ax ;* always code
cCall DebugDefineSegment,<cx,psDest,ax>
ENDIF ;KEEP_SYMDEB_CODE
mov ax,psDest ;* return value
cEnd LoadSegment
loads_error:
;* * close file and try to open again
;* * if retrying twice, prompt with error line
mov ah,iexeCur ;* re-open it
jmp loads_retry
;*****************************************************************************
;********** StrCpySiDi **********
;* entry : ds:si => source
;* es:di => destination
;* * copy and zero terminate
;* exit : es:di => next destination
cProc StrCpySiDi, <NEAR, ATOMIC>
cBegin StrCpySiDi
copy_lp:
lodsb
stosb
or al,al
jnz copy_lp
cEnd StrCpySiDi
;********** OpenSwapFile **********
;* entry : ah = iexe to open
;* DS = psLom
;* fFreeOpen => open before prompt
;* (FALSE => prompt before open)
;* * open the swap file (prompt and don't return till open)
;* exit : n/a (fdExeLom and iexeCur updated).
;* Kernel buffer filled with RLB info
;* * TRASHES : DI
;* * NOTE : will always open !!
cProc OpenSwapFile, <NEAR, ATOMIC>, <SI>
cBegin OpenSwapFile
assumes DS,NOTHING
xchg ah,iexeCur ;* set iexeCur, get old
or ah,ah
js no_file_open ;* negative => 0FFH => closed
;* * close old file first
mov bx,ds:[fdExeLom]
AssertNE bx,-1
mov ah,3eh
int 21h ;* close file, ignore errors !!
no_file_open:
;* * otherwise open swap file (ds == psLom, iexeCur set up)
retry_open: ;* old file already closed
cCall GetProgFileName
mov cx,fFreeOpen
jcxz open_file_error ;* prompt first
;* ds:dx => string
mov ax,3d00h
int 21h ;* open for reading
jnc open_file_ok ;* open success
;* * error when trying to find file (DS = psLom)
open_file_error:
cCall GetProgFileName
push ds ;* save psLom
Assert <?PLM>
IFNDEF NOPCODE
push fNew
ENDIF ;!NOPCODE
;* push lszPath
push ds
push dx
;* push ifile
xor ax,ax
mov al,iexeCur
push ax ;* parm.
;* restore DS to DDS
push ss
pop ds
assumes DS,DGROUP
xor ax,ax ;* pinst == NULL => prev mode
cCall FInitScreenInternal, <ax> ;* to text mode !!
cCall PromptSwapDisk ;* tell the user
mov ah,0DH
int 21h ;* reset disk to try again
IFNDEF NOPCODE
pop fNew
ENDIF ;!NOPCODE
mov fFreeOpen,sp ;* allow retry
pop ds ;* restore psLom
assumes DS,NOTHING
jmp retry_open
open_file_ok:
AssertNE ax,-1
mov ds:[fdExeLom],ax ;* save fd
IFDEF DUAL
;* * reading rlb is done by LoadSegment
ELSE ;!DUAL
;* * now read in rlb for moveable segments (rlbMove or rlbSwap)
;* * assume main swap file
mov bx,ax ;* fd
mov dx,word ptr ds:[neLom.ne_lfaRlbMove] ;* low word
mov cx,word ptr ds:[neLom.ne_lfaRlbMove+2] ;* high word
mov ax,ds:[neLom.ne_cbRlbMove] ;* size
cmp iexeCur,0
je reload_rlb ;* all set to go
;* * auxiliary swap file : read EXH header
xor cx,cx
xor dx,dx ;* lfa = 0 (start of file)
mov ax,SIZE EXH
cCall ReadKernelBuff ;* return ss:bx => buffer
jc after_open_error
;* * Validate swap file (must have proper signature, application version
;* * stamp and swap file #).
cmp ds:[bx].magicExh,magicNe
jne after_open_error ;* bad signature
mov si,ds:[neLom.ne_restab] ;* start of offsets
mov al,ds:[si-1] ;* chStamp
cmp ds:[bx].chStampExh,al
jne after_open_error ;* bad version stamp
mov al,iexeCur
cmp ds:[bx].ifileExh,al
jne after_open_error ;* bad swap file #
mov dx,word ptr ds:[bx].lfaRlbExh ;* low word
mov cx,word ptr ds:[bx].lfaRlbExh+2 ;* high word
mov ax,ds:[bx].cbRlbExh ;* size
mov bx,ds:[fdExeLom] ;* restore fd
reload_rlb: ;* Load/Reload RLB into kernel work buffer
;* cx:dx = lfa, ax = cb, bx = fd
;* * now read in RLB info (into kernel buffer), ax = cb, bx = fd
cCall ReadKernelBuff ;* return ss:bx => buffer
;* cx = fd
jc after_open_error
cmp ds:[bx].magicRlb,magicNe
jne after_open_error ;* bad signature
ENDIF ;!DUAL
;* * success !!
cEnd OpenSwapFile
after_open_error: ;* opened
;* * close file
mov bx,ds:[fdExeLom]
AssertNE bx,-1
mov ah,3eh
int 21h ;* close file, ignore errors !!
jmp open_file_error
;********** GetProgFileName **********
;* entry : n/a (DS == psLom)
;* * copy program drive/dir + file_name into far kernel buffer
;* exit : ds:dx = start of string (in far kernel buffer)
;* NOTE : Trashes SI & DI.
cProc GetProgFileName, <NEAR, PUBLIC, ATOMIC>
cBegin GetProgFileName
mov di,ds:[offRlbLom]
mov dx,di ;* start of string
push ds
pop es ;* es:di => rlb buffer
;* (far kernel buffer)
mov si,lomOffset szBootPathLom
cCall StrCpySiDi
dec di ;* don't terminate
mov al,iexeCur
mov si,lomOffset szExeLom
or al,al
jnz @F ;* use szExeLom if 0
test byte ptr ds:[si],0ffh
jnz use_sz ;* ...and szExeLom is set
@@:
xor ah,ah
shl ax,1
mov bx,ax
mov si,ds:[neLom.ne_restab] ;* start of offsets
add si,ds:[si+bx] ;* to proper string
use_sz:
cCall StrCpySiDi
cEnd GetProgFileName
IFDEF DUAL
;********** GetRle ***************
;* entry: ds:di => neLom
;* al == segno
;* * Return pointer to Rlb entry in Rlbtab for this segment
;* exit: bx => Rle
;* * only bx changed
cProc GetRle,<PUBLIC,NEAR>
cBegin GetRle
;* * Check correct RLB is loaded
mov bx,ds:[di].ne_rlbtab
grle_next_rlb_ent:
cmp al,ds:[bx].re_segLast
jbe grle_rlb_done
add bx,SIZE RLB_ENT
jmp short grle_next_rlb_ent
grle_rlb_done:
cEnd GetRle
;********** LoadRle ***************
;* entry: ds == psLom
;* bx => Rle
;* * Load rlb for given rle
;* exit: see ReadKernelBuff for return values
cProc LoadRle,<PUBLIC,NEAR>
cBegin LoadRle
;* * load correct rlb
mov ds:[pbRleCurLom],bx ;* set new marker
mov dx,ds:[bx].LO_re_lfaRlb
mov cx,ds:[bx].HI_re_lfaRlb
sub dx,ds:[bx].LO_re_dlfaBias
sbb cx,ds:[bx].HI_re_dlfaBias
mov ax,ds:[bx].re_cbRlb
mov bx,ds:[fdExeLom]
cCall ReadKernelBuff
cEnd LoadRle
ENDIF ;DUAL
;********** ReadKernelBuff **********
;* entry : ax = # of bytes to read
;* cx:dx = lfa
;* bx = fd
;* ds == psLom
;* * seek and read # of bytes into far kernel buffer
;* exit : CY => error
;* else: ds:bx => start of kernel buffer,
;* cx = fd
;* * DS retained (access buffer off of ss:bx).
cProc ReadKernelBuff, <NEAR, ATOMIC>
cBegin ReadKernelBuff
AssertEQ bx,ds:[fdExeLom]
push ax
mov ax,4200h ;* seek device, from start
int 21h
pop cx ;* cx = # of bytes
jc read_kern_fail ;* seek error
mov dx,ds:[offRlbLom]
mov ah,3fh ;* read from file
int 21h
jc read_kern_fail ;* read error
cmp ax,cx
stc
jne read_kern_fail ;* didn't read it all
mov cx,bx ;* save fd
mov bx,dx ;* ds:bx => buffer
clc
read_kern_fail:
cEnd ReadKernelBuff
;*****************************************************************************
;********** AccessSwapFile **********
;* entry : fOpen : TRUE => be sure default swap file is open
;* FALSE => be sure all swap files are closed
;* * enable / disable the swap file
;* exit : n/a
cPublic AccessSwapFile, <ATOMIC>, <DS, DI>
parmW fOpen
cBegin AccessSwapFile
assumes DS,DATA
mov ds,psLom
assumes DS,NOTHING
mov cx,fOpen
jcxz close_swap_file
;* * if iexeCur != 0, then open swap file #0
xor ah,ah ;* swap file # 0
cmp ah,iexeCur
je end_access_swap_file ;* already open
;* * open the default swap file (ah == 0)
mov fFreeOpen,sp ;* allow 1 free open
cCall OpenSwapFile
end_access_swap_file:
cEnd AccessSwapFile
close_swap_file:
mov ax,-1
xchg iexeCur,al ;* stuff 255 into iexeCur, get old
cmp ah,al
je end_access_swap_file ;* already closed
mov bx,ds:[fdExeLom]
AssertEQ iexeCur,255
AssertNE bx,-1
mov ah,3eh
int 21h ;* close file
jmp short end_access_swap_file
;*****************************************************************************
sEnd KERNEL
;*****************************************************************************
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -