commit Bart's patch to fix CP/M call psp:05h compatibility call along with some comments to explain the call trampoline

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1372 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Kenneth J Davis 2009-05-01 04:25:27 +00:00
parent 497a2337ef
commit 240bcc30e2
2 changed files with 68 additions and 58 deletions

View File

@ -65,14 +65,22 @@ typedef struct {
UWORD ps_exit; /* 00 CP/M-like exit point: int 20 */ UWORD ps_exit; /* 00 CP/M-like exit point: int 20 */
UWORD ps_size; /* 02 segment of first byte beyond */ UWORD ps_size; /* 02 segment of first byte beyond */
/* memory allocated to program */ /* memory allocated to program */
BYTE ps_fill1; /* 04 single char fill */ BYTE ps_fill1; /* 04 single char fill=0 */
/* CP/M-like entry point */ /* CP/M-like entry point */
UBYTE ps_farcall; /* 05 far call opcode */ /* offsets 5-9 are a far call to absolute address 0:000Ch
coded so that CP/M apps can do a near call to psp:5, does a
far call but ensures word at offset 6 is size of COM file
e.g. FEF0h by using 1MB wrap around address 0F01D:FEF0
(jmp code stored at 0:000C should be duplicated in HMA FFFF:00D0)
Note: MS-DOS has value as FEEE which wraps to 0:00BEh */
UBYTE ps_farcall; /* 05 far call opcode */
VOID(FAR ASMCFUNC * ps_reentry) (void); /* 06 re-entry point */ VOID(FAR ASMCFUNC * ps_reentry) (void); /* 06 re-entry point */
intvec ps_isv22, /* 0a terminate address */
ps_isv23, /* 0e break address */
ps_isv24; /* 12 critical error address */ intvec ps_isv22, /* 0a terminate address */
ps_isv23, /* 0e break address */
ps_isv24; /* 12 critical error address */
UWORD ps_parent; /* 16 parent psp segment */ UWORD ps_parent; /* 16 parent psp segment */
UBYTE ps_files[20]; /* 18 file table - 0xff is unused */ UBYTE ps_files[20]; /* 18 file table - 0xff is unused */
UWORD ps_environ; /* 2c environment paragraph */ UWORD ps_environ; /* 2c environment paragraph */

View File

@ -28,10 +28,10 @@
; $Id$ ; $Id$
; ;
%include "segs.inc" %include "segs.inc"
%include "stacks.inc" %include "stacks.inc"
segment HMA_TEXT segment HMA_TEXT
extern _int21_syscall extern _int21_syscall
extern _int21_service extern _int21_service
extern _int2526_handler extern _int2526_handler
@ -50,7 +50,7 @@ segment HMA_TEXT
extern _Int21AX:wrt DGROUP extern _Int21AX:wrt DGROUP
extern _DGROUP_ extern _DGROUP_
global reloc_call_cpm_entry global reloc_call_cpm_entry
global reloc_call_int20_handler global reloc_call_int20_handler
@ -65,9 +65,14 @@ segment HMA_TEXT
; VOID FAR ; VOID FAR
; cpm_entry(iregs UserRegs) ; cpm_entry(iregs UserRegs)
; ;
; This one is a strange one. The call is to psp:0005h but it returns to the ; For CP/M compatibility allow a program to invoke any DOS API function
; function after the call. What we do is convert it to a normal call and ; between 0 and 24h by doing a near call to psp:0005h which embeds a far call
; fudge the stack to look like an int 21h call. ; to absolute address 0:00C0h (int vector 30h & 31h) or FFFF:00D0 (hma).
; Note: int 31h is also used for DPMI
; Upon entry the stack has a near return offset (desired return address) and
; far return seg:offset (useless return to data at offset 0ah after far call
; in psp). We convert it to a normal call and correct the stack to appear same
; as if invoked via an int 21h call including proper return address.
; ;
reloc_call_cpm_entry: reloc_call_cpm_entry:
; Stack is: ; Stack is:
@ -75,10 +80,7 @@ reloc_call_cpm_entry:
; psp seg ; psp seg
; 000ah ; 000ah
; ;
push bp ; trash old return address add sp, 2 ; remove unneeded far return offset 0ah
mov bp,sp
xchg bp,[2+bp]
pop bp
pushf ; start setting up int 21h stack pushf ; start setting up int 21h stack
; ;
; now stack is ; now stack is
@ -107,12 +109,12 @@ reloc_call_cpm_entry:
; psp seg (alias .COM cs) ; psp seg (alias .COM cs)
; return offset ; return offset
; ;
cmp cl,024h cmp cl,024h ; restrict calls to functions 0-24h
jbe cpm_error ja cpm_error
mov ah,cl ; get the call # from cl to ah mov ah,cl ; get the call # from cl to ah
jmp reloc_call_int21_handler ; do the system call jmp reloc_call_int21_handler ; do the system call
cpm_error: mov al,0 cpm_error: mov al,0
iret iret ; cleanup stack and return to caller
; ;
; interrupt zero divide handler: ; interrupt zero divide handler:
@ -123,20 +125,20 @@ cpm_error: mov al,0
; int20_handler(iregs UserRegs) ; int20_handler(iregs UserRegs)
; ;
print_hex: mov cl, 12 print_hex: mov cl, 12
hex_loop: hex_loop:
mov ax, dx mov ax, dx
shr ax, cl shr ax, cl
and al, 0fh and al, 0fh
cmp al, 10 cmp al, 10
sbb al, 69h sbb al, 69h
das das
mov bx, 0070h mov bx, 0070h
mov ah, 0eh mov ah, 0eh
int 10h int 10h
sub cl, 4 sub cl, 4
jae hex_loop jae hex_loop
ret ret
divide_by_zero_message db 0dh,0ah,'Interrupt divide by zero, stack:',0dh,0ah,0 divide_by_zero_message db 0dh,0ah,'Interrupt divide by zero, stack:',0dh,0ah,0
@ -159,27 +161,27 @@ zero_message_loop:
jmp short zero_message_loop jmp short zero_message_loop
zero_done: zero_done:
mov bp, sp mov bp, sp
xor si, si ; print 13 words of stack for debugging LUDIV etc. xor si, si ; print 13 words of stack for debugging LUDIV etc.
stack_loop: stack_loop:
mov dx, [bp+si] mov dx, [bp+si]
call print_hex call print_hex
mov al, ' ' mov al, ' '
int 10h int 10h
inc si inc si
inc si inc si
cmp si, 13*2 cmp si, 13*2
jb stack_loop jb stack_loop
mov al, 0dh mov al, 0dh
int 10h int 10h
mov al, 0ah mov al, 0ah
int 10h int 10h
mov ax,04c7fh ; terminate with errorlevel 127 mov ax,04c7fh ; terminate with errorlevel 127
int 21h int 21h
sti sti
thats_it: hlt thats_it: hlt
jmp short thats_it ; it might be command.com that nukes jmp short thats_it ; it might be command.com that nukes
invalid_opcode_message db 0dh,0ah,'Invalid Opcode at ',0 invalid_opcode_message db 0dh,0ah,'Invalid Opcode at ',0
@ -299,7 +301,7 @@ int21_1:
; I don't know who needs that, but ... (TE) ; I don't know who needs that, but ... (TE)
; ;
mov word [_user_r+2],ss mov word [_user_r+2],ss
mov word [_user_r],bp ; store and init mov word [_user_r],bp ; store and init
; ;
; Decide which stack to run on. ; Decide which stack to run on.
@ -377,9 +379,9 @@ int21_exit_nodec:
%ifdef WATCOM %ifdef WATCOM
sub bp, 4 ; for fs and gs only sub bp, 4 ; for fs and gs only
%else %else
sub bp, 6 ; high parts of eax, ebx or ecx, edx sub bp, 6 ; high parts of eax, ebx or ecx, edx
%endif %endif
%endif %endif
cli cli
mov ss,si mov ss,si
@ -387,7 +389,7 @@ int21_exit_nodec:
int21_ret: int21_ret:
Restore386Registers Restore386Registers
POP$ALL POP$ALL
; ;
; ... and return. ; ... and return.
@ -466,8 +468,8 @@ int2526:
Protect386Registers Protect386Registers
push dx push dx
push cx ; save user stack push cx ; save user stack
push dx ; SS:SP -> user stack push dx ; SS:SP -> user stack
push cx push cx
@ -475,8 +477,8 @@ int2526:
call _int2526_handler call _int2526_handler
add sp, byte 6 add sp, byte 6
pop cx pop cx
pop dx ; restore user stack pop dx ; restore user stack
Restore386Registers Restore386Registers