📄 cstart.asm
字号:
; save the command processor's __psp variable, and then set it to the
; psp of the process that called us. This is so that the Break and
; Criterr abort code can correctly determine whether the int2e command
; was internal or external
mov ah, MS_P_GETPSP
int DOS_INT
push bx ; save calling process's psp - EJH
mov bx, [__psp]
; Set current PSP to our own - EJH
mov ah, MS_P_SETPSP
int DOS_INT
; call C code
mov ax, code_seg
mov i2e_c_seg, ax
push i2e_cmd
call i2e_c_entry
pop ax ; clean up stack
; Set current psp back to that of calling process - EJH
pop bx
mov ah, MS_P_SETPSP
int DOS_INT
; restore interrupt vecs
push ds
lds dx, i2e_i23vec
mov ax, (MS_S_SETINT*256) + 23h
int DOS_INT
lds dx, cs:i2e_i24vec
mov ax, (MS_S_SETINT*256) + 24h
int DOS_INT
pop ds
cmp high_code, TRUE ; If not a .EXE then free
jnz i2e_ret ; any memory alocated by
call free_com_memory ; the Command Processor
i2e_ret:
i2e_exit:
; swap back the stack
cli
mov ss, i2e_user_ss
mov sp, i2e_user_sp
sti
i2e_exit2:
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
sub ax, ax
mov cs:i2e_lock, 0
ret 2
int2E_far_entry endp
_TEXT SEGMENT
assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing
public _exec ; EXEC routine
;
; WORD CDECL exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back);
;
; back 10[bp]
; line 08[bp]
; type 06[bp]
; path 04[bp]
;
_exec:
;-----
push bp
mov bp,sp
push si
push di
push ds
push es
inc in_exec
cmp in_exec,1
je _exec10 ; Menuing system
push exec_ss ; save old stack_save if we
push exec_sp ; are being re-entered
_exec10:
mov si,08[bp] ; the Command Line
mov exec_env,0000
mov exec_clineoff,si
mov exec_clineseg,ds
mov exec_fcb1seg,ds
mov exec_fcb2seg,ds
push ds
pop es
;
; Extract two valid filenames from the CR terminated
; string passed in DS:SI. The FCBs will be generated in FCB1 and FCB2.
;
inc si
mov di,dataOFFSET fcb1 ; Blank fill the first FCB
call zap_fcb
call make_fcb ; Build first FCB
mov di,dataOFFSET fcb2 ; Blank fill the Second FCB
call zap_fcb
call make_fcb ; Build second FCB
mov ax,cs
jmp exec ; do FAR jmp to msdos_exec as we can't
_exec_ret: ; trust the stack when CALLing
dec in_exec ; Has PCTOOLS un-installed itself ?
jz _exec20 ; No so the stack contents are valid
js _exec_bad ; Yes, so exit by Ctrl-Break
pop exec_sp ; old stack save back again
pop exec_ss ; in the case of re-entry
_exec20:
pop es
pop ds
pop di
pop si
pop bp
mov ax,return_code
neg ax
ret
;
; We have returned from the EXEC function un-expectedly (because
; of PCTOOLS De-installation ?). Therefore the contents of the stack
; are invalid and we generate a Control-Break.
;
_exec_bad:
mov ax,0100h ; Termination Code Control-C Abort
push ax ; Save on the Stack for C routine
push ax ; Force a dummy return address on stack
mov in_exec,al ; zero in_exec count for next time
extrn _int_break:near ; C Break/Error handling routine
jmp _int_break ; now treat as ctrl-break
;
; Initialise the FCB entry a DX:DI and copy the Drive, FileName
; and extension form DS:SI when SI != 0FFFFh
;
zap_fcb:
mov ax,2000h ; Zero Fill first byte and last 4
stosb ; Drive code 0
xchg al,ah
mov cx,11 ; FileName and Ext to ' '
rep stosb
xchg al,ah
mov cl,4 ; Last four bytes to 00
rep stosb
sub di,16
ret
make_fcb:
call scan_filechar ; Get the Next File Character
push si
push di
push ax ; Save Character and Pointers
mov ax,(MS_F_PARSE shl 8) + 1 ; Parse the command line
int DOS_INT
pop ax
pop di ; Restore the Character and Pointer
cmp ah,'/' ; Was the arg preceeded by a '/'
jne make_fcb10 ; If it was roll back the cmd line
pop si ; pointer and blank all but the 1st
inc si ; char in the FCB
add di,2 ; Such that /FRED gives an FCB of 'F'
mov cx,10 ; and si points to the 'R'
mov al,' '
rep stosb
ret
make_fcb10:
pop ax ; discard original SI, skip name
jmp scan_sepchar ; skip until separator
;
; SCAN_SEPCHAR will search through the command line DS:SI
; which contains CX characters and return with SI pointing
; to the next SEPARATOR character.
;
; On Entry: DS:SI Character String
;
; On Exit: DS:SI First Non Separator
;
scan_sepchar:
push di ; Save DI ES points at this segment
mov ah,0 ; Invalidate Separator Character
scan_s10:
mov al,[si] ; Get the Character to Test
cmp al,CR
jz scan_s20 ; Have we reached the end of the string
mov cx,legal_length ; Scan the table of legal
mov di,dataOFFSET legal_table ; separators
repnz scasb ; Scan the List
jz scan_s20 ; Separator Located
inc si ; the character pointer
jmp SHORT scan_s10
scan_s20:
pop di
ret
;
; SCAN_FILECHAR will search through the command line DS:SI
; and return with SI pointing to the next NON_SEPARATOR character.
;
; On Entry: DS:SI Character String
;
; On Exit: DS:SI First Non Separator
; AH Last Valid Separator
;
scan_filechar:
push di ; Save DI ES points at this segment
mov ah,0 ; Invalidate Separator Character
scan_f10:
mov al,[si] ; Get the Character to Test
cmp al,CR
jz scan_f20 ; Have we reached the end of the string
mov cx,legal_length ; Scan the table of legal
mov di,dataOFFSET legal_table ; separators
repnz scasb ; Scan the List
jnz scan_f20 ; Non Separator Located
mov ah,al ; Save the Separator and increment
inc si ; the character pointer
jmp SHORT scan_f10
scan_f20:
pop di
ret
_TEXT ENDS
legal_table db ':.;,=+',9,' /<>|',22h,'[]'
legal_length equ 15
assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing
public msdos_exec ; so it shows in map file
msdos_exec PROC FAR
push ax
cmp high_code,TRUE ; Check if the Command Processor Code
jnz msdos_e10 ; has been relocated to high memory
call free_com_memory ; free cmd processor memory
msdos_e10:
pop ax
mov bx,dataOFFSET exec_block
mov dx,04[bp] ; Get the Full Command Name
mov exec_ss,ss ; Save SS:SP in case somebody (NOVELL)
mov exec_sp,sp ; corrupts them
; The following 2 JMPF are kludged so that the INT22 vector saved in
; the child's PSP has the segment of the comand processors PSP.
; This is vital for many TSR management utilities.
;
; swap stack to conventional memory
cli ;
mov ax,__psp ;
mov ss,ax ;
mov sp,0100h ;
sti ;
db 0EAh ; JMPF Opcode
dw dataOFFSET psp_dofunc4b ; Corrected Offset
exec_psp dw 0 ; PSP Segment
assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing
func4b_return:
mov ss,exec_ss ; Restore the real SS:SP
mov sp,exec_sp ; Using a CS overide
jc msdos_e20 ; if no error
xor ax,ax ; then zero return code
jmp msdos_e21
msdos_e20:
mov ah,59h ; get extended error code
sub bx,bx
int 21h
msdos_e21:
mov return_code,ax
call get_ds ; Point DS & ES to CSdata
mov ds,ax
mov es,ax
assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing
call handler_init ; Re-initialise Control-Break and
; Critical error handlers for Novell
cmp high_code,TRUE ; Is the Command Code in High
jnz msdos_e30 ; memory ?
mov reload_flag,1 ; Reloading Command Processor
call reload_code ; Reload Command Processor Code
mov reload_flag,0 ; Command Processor Loaded
msdos_e30:
mov ax,code_seg ; Update the CS for the high code
mov msdos_exec_ret_seg,ax ; in case it has moved and return
jmp msdos_exec_ret
msdos_exec ENDP
_TEXT SEGMENT
assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing
Public _readline
_readline:
;---------
cld
push bp
mov bp,sp
push si
push di
push es
ifdef DOSPLUS
mov ax,4456h ; Swap to the Command process
mov dl,1 ; History Buffer in DR DOS
int DOS_INT
else
push ds
call get_history_buffers ; get history buffers
mov P_SB_SEG[bx],ax ; swap to command one
pop ds
endif
mov ax,5d09h
int DOS_INT ; close remote spool files
mov ax,5d08h
mov dl,1
int DOS_INT ; Set truncate flag with redirected I/O
mov ah,MS_P_GETPSP ; get the current PSP
int DOS_INT ; then compare the STDERR entry in the
mov es,bx ; XFT with the Magic Number for CON
cmp es:byte ptr [18h+STDERR],1
mov dx,4[bp] ; get the buffer address and current
mov ax,cs ; AX = transient code segment
call readline ; do far call to msdos_readline
ifdef DOSPLUS
mov ax,4456h ; Swap to the Application process
mov dl,0 ; History Buffer in DR DOS
int DOS_INT
else
push ds
call get_history_buffers ; get history buffers
mov P_SB_SEG[bx],dx ; swap to application one
pop ds
endif
pop es
pop di
pop si
pop bp
ret
ifdef CDOS
get_history_buffers proc near
; On Entry:
; None
; On Exit:
; AX = command history buffers
; DX = application history buffers
; DS:BX -> pd
; NB. both DS and ES are corrupted by this call
;
mov ds,_sysdat_seg ; DS points to SYSDAT and ES to the
mov bx,ds:word ptr [68h] ; current process's UDA
mov dl,P_CNS[bx] ; DL = console number
mov es,P_UDA[bx]
push bx
mov ax,XIOS_HISTBUF ; Get the History Buffer Address's
call XIOS_ENTRY ; by calling ths XIOS
pop bx
ret
get_history_buffers endp
endif
_TEXT ENDS
assume cs:DGROUP, ds:DGROUP, es:nothing
;
; msdos_readline(BYTE *buffer);
;
; On Entry:
; flags - ZF set if we need to do Sidekick Plus check
; DS:DX -> buffer
; AX:0 -> Resident Section
; buffer
;
; The memory allocation for the hi-mem part of command.com has already been
; altered to minimise the chances of SideKick Plus overwriting the code.
; But it still can happen, say either on a machine with limited memory or
; other TSR's also loaded. In order to cater for this case we move the actual
; readline call into the resident portion and checksum things before returning
; to high memory - thus we can reload command.com if it get overwritten.
;
msdos_readline PROC FAR
pushf ; save the result for later
mov bx,sp ; SP before swapping stacks.
cli ; to RLSTACK
mov ss,ax ; above the Code and Messages
mov sp,codeOFFSET rlstack
sti
push bx ; save old SP
push ds
sub sp,260 ; make room for buffer on stack
mov di,sp ; save the address
push ds
push dx ; save real BUFFER for later...
push di ; and buffer on stack
mov si,dx ; point DS:SI at real buffer
mov dx,di ; point DX at stack buffer
push ss ; now get all the seg regs
pop es ; pointing to himem
mov cx,256/2
rep movsw ; copy resident buffer to stack
push ss ; DS:DX is stack buffer
pop ds
mov ax,4810h ; give DOSKEY a chance
int 2Fh
or ax,ax ; zero means DOSKEY has done it
jz msdos_rl10
mov word ptr [di],21cdh ; poke INT 21 and
mov byte ptr 2[di],0cbh ; RETF instruction
push cs ; save an address for the
mov ax,dataOFFSET msdos_rl10; RETF to return to
push ax
mov ah, MS_C_READSTR ; parameter for INT 21 readline
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -