Hi, I'm trying to make a simple program that spawns a secondary
shell (exec COMSPEC...). What I've done works under the Causeway DOS
Extender, but crashes with DOS/4GW. If anybody could help me find what's
wrong with this code, I'd appreciate it a lot.
----- shell.asm ----------------------------------------------------------
ideal
p486
model flat
stack
codeseg
Start:
jmp _over
db 'WATCOM'
_over:
cld
mov ax,ds
mov [_psp1],ax
mov ax,es
mov [_psp2],ax
mov [_psp3],ax
mov ax,[word es:002ch]
mov [_env_sel],ax
mov bx,ax
mov ax,0006h
int 31h ; Get Segment Base (CX:DX)
mov [word _environ],dx
mov [word _environ+2],cx
mov ax,ds
mov es,ax
mov esi,offset DOS_Shell$ ; ESI -> 'COMSPEC', 00h
call _getenv ; EAX -> Ptr to Shell
; eg. 'C:\DOS\COMMAND.COM', 00h
mov ebx,offset DOS_Shell_Tail$ ; EBX -> 00h, 0dh
mov [_cmd_tail],ebx ; Store ptr to Command Tail in
; _exec_block struct
mov edx,eax
mov ebx,offset _exec_block
mov eax,4b00h
int 21h ; DOS EXEC
_exit:
mov ah,4ch
int 21h ; DOS EXIT
; EAX = _getenv(ESI)
_getenv:
push esi edi
call _strlen
mov edi,[_environ]
_getenv_try_next:
cmp [byte edi],00h
jz _getenv_end
call _strncmp
test eax,eax
jz _getenv_yeap
_getenv_skip:
cmp [byte edi],00h
jz _getenv_next
inc edi
jmp _getenv_skip
_getenv_next:
inc edi
jmp _getenv_try_next
_getenv_yeap:
mov eax,edi
add eax,ecx
inc eax
jmp _getenv_exit
_getenv_end:
mov eax,edi
_getenv_exit:
pop edi esi
ret
; ECX = _strlen(ESI)
_strlen:
push eax esi
xor ecx,ecx
xor al,al
_strlen_1:
cmp [esi],al
jz _strlen_2
inc ecx
inc esi
jmp _strlen_1
_strlen_2:
pop esi eax
ret
; EAX = _strncmp(ESI, EDI, ECX) (zero -> equal, non-zero -> not equal)
_strncmp:
push ecx esi edi
_strncmp_l1:
test ecx,ecx
jnz _strncmp_l3
_strncmp_l2:
xor eax,eax
_strncmp_exit:
pop edi esi ecx
ret
_strncmp_l3:
mov bl,[esi]
mov bh,[edi]
cmp bl,bh
je _strncmp_l4
mov eax,1
jmp _strncmp_exit
_strncmp_l4:
cmp [byte esi],00h
je _strncmp_l2
inc esi
inc edi
dec ecx
jmp _strncmp_l1
dataseg
DOS_Shell$ db 'COMSPEC', 00h
DOS_Shell_Tail$ db 00, 0dh
label _exec_block
_env_sel dw 0000h
_cmd_tail dd 00000000h
_psp1 dw 0000h
dd 0000005ch
_psp2 dw 0000h
dd 0000006ch
_psp3 dw 0000h
_environ dd ?
end Start
---------------------------------------------------------------------------
This is the error message I got from DOS/4GW with environment
variable DOS4G=verbose
----------- dos4gw.log ----------------------------------------------------
Error initializing mouse: 2
Loading with LINEXE_LOADER
Executing D:\PROJECT\ADS32\SHELL.EXE with initial registers:
TSF32: prev_tsf32 0
SS 158 DS 158 ES 28 FS 0 GS 20
EAX 0 EBX 0 ECX 0 EDX 0
ESI 150 EDI 0 EBP 0 ESP 141410
CS:IP 150:0013F000 ID 00 COD 168588E FLG 200
CS= 150, USE32, page granular, limit FFFFFFFF, base 0, acc CF9B
DS= 158, USE32, page granular, limit FFFFFFFF, base 0, acc CF93
ES= 28, USE16, byte granular, limit FF, base DA40, acc 93
SS= 158, USE32, page granular, limit FFFFFFFF, base 0, acc CF93
DOS/4GW error (2001): exception 0Dh (general protection fault) at 70:00001634
TSF32: prev_tsf32 4FC0
SS 98 DS 98 ES 20 FS 0 GS 20
EAX D00 EBX 2380 ECX 0 EDX 20
ESI 141294 EDI 2430 EBP 4E66 ESP 4E60
CS:IP 70:00001634 ID 0D COD 4FFE00D8 FLG 10006
CS= 70, USE16, byte granular, limit 596F, base 11C160, acc 9B
SS= 98, USE16, byte granular, limit 7CFF, base 153DF0, acc 93
DS= 98, USE16, byte granular, limit 7CFF, base 153DF0, acc 93
ES= 20, USE16, byte granular, limit FFFF, base DB40, acc 93
FS= 0, USE16, byte granular, limit 0, base 14, acc 0
GS= 20, USE16, byte granular, limit FFFF, base DB40, acc 93
CR0: PG:0 ET:1 TS:0 EM:0 MP:0 PE:1 CR2: 10053C4C CR3: 4B14
DOS/4GW deinitializing
... deinitializing LINEXE_LOADER
... deinitializing D32_INT31
... deinitializing int31 package
--------------------------------------------------------------------------
I think the program crashes when it reaches a 'lds si,[bx+82]' or
something like that, which is not in my code, I guess it's in DOS code, but
for some reason that memory can't be accessed (the WATCOM de{*filter*} can't
show me the memory contents)
Hope somebody helps me,