X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f X-Recipient: djgpp AT delorie DOT com X-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:in-reply-to:references:to:from :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=kEb7efQnSdfRSlcBFe9sCnv2uTiYHVBBUdrgpbU1Uak=; b=Ma32fWMMu8S+9/Amj+k/dh90HaugmwmT+DacbB7Hk834U7qOcNQCZEndeY1Z8OZhy/ m2Ld8YBjQTdgDg57aoaLuUGvLlA0CE9ZM9Y/oZp+mC6haVRsPudl52JMJ8sGmz31F0rN wSHdrhdAW+t48rERNlLZ3VNvR1KVKQJ6lpYQvw/T6GUlpT1tGutn+0byAm1bk49KiI4o jNlxKWAbYA6l6CRDGT0sUDLjF/IhGdW4UjilTA+mLlddOM/ElbWOmvb8n9dtfU5peAny F43xIchhLlYYQQgcCNhV3JjLhyRsvFEpmjeLNAWb0RQpSZeOTAE9CNUKF5IG2r6fdMVc uJZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:references:to:from :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=kEb7efQnSdfRSlcBFe9sCnv2uTiYHVBBUdrgpbU1Uak=; b=VkCkyFEMR3IZfj+YXTjEEwgD7NKbPbznE+rbF+a7UIvCC4noVGz+PPbIJZBrJQ05WK kg+ZvNCnY0pasJ8gJgD9HuMnAF/ZeBZajjVPGyhkxO1TOfRI+diqLTO47tqSUHt0sLcH seXkoFh/xm5MXwLCoOdeN07I84f+hOUkbErI2Ak8j2yBqNa09dgrScBRk6OH/ms5oFEE RgHuJJd9QuPwj5f3wY3rnB4X5IKFNmK8dKQ1i4CUBJaglghaA3h7NnvkvFd0O6XzJIdu fgSBL03bioARIIElErQ5QYhKepXTi5xYhwsspzwyhevbERMMs5tIjDPXXW2Jd8xmUIHF yVuQ== X-Gm-Message-State: ANoB5pnWI9dWq8yk7cu+fB1WTvUun3qGjVnrXj1U4d9ExtiNZTvVQoPL TL0xU23RwEXfO3zmyfaeSThYDxSa6oA= X-Google-Smtp-Source: AA0mqf7qrg0Quu0WGTj7MfTFbKSBhO+RWwfz5pVNZ81C7xa7ozsmxN85U0DqGAtmswwmSIPvf0vXQA== X-Received: by 2002:a17:906:f113:b0:7ad:a030:7501 with SMTP id gv19-20020a170906f11300b007ada0307501mr29798264ejb.446.1669332412645; Thu, 24 Nov 2022 15:26:52 -0800 (PST) Message-ID: <21e1aa0b-1511-0071-84c0-b20c6a3d1dae@gmail.com> Date: Fri, 25 Nov 2022 00:26:51 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.5.0 Subject: [PATCH v2] stub: ignore host exit status Content-Language: en-US From: "J.W. Jagersma (jwjagersma AT gmail DOT com) [via djgpp AT delorie DOT com]" To: djgpp AT delorie DOT com References: <744f054f-9682-4a05-91ad-684b18c0122b AT gmail DOT com> In-Reply-To: <744f054f-9682-4a05-91ad-684b18c0122b@gmail.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Reply-To: djgpp AT delorie DOT com On 2022-11-23 20:47, J.W. Jagersma wrote: > Hi all, > > If you've ever tried using hdpmi32 with a djgpp program, you may have > noticed some strange behavior. The program first fails to run with > "Load error: no DPMI", but on the second try, it suddenly works. Then > a third invocation fails again, the fourth runs fine, etc. > > When you rename 'hdpmi32.exe' to 'cwsdpmi.exe', your program seems to > run consistently. But this is only because there is a second (real) > cwsdpmi in your PATH somewhere. What really happens, is that your > program alternates between running under hdpmi and cwsdpmi. > > I finally figured out why this happens, and it's very simple: hdpmi uses > the exit status to indicate if it was loaded via xms, vcpi, or int15. > And the djgpp stub considers any non-zero exit status to be a failure, > so it keeps searching PATH until cwsdpmi is found, which always returns > zero. > > For a possible solution, I would suggest to ignore the return status > from the host, and just check int 2f/1687 after every exec. As an added > bonus, this saves 13 bytes of stub space. Amended patch follows - it no longer skips the last iteration (exec with no path). It's a bit larger, but still saves 6 bytes in total. --- a/src/stub/stub.asm +++ b/src/stub/stub.asm @@ -199,38 +199,49 @@ not_path: ;----------------------------------------------------------------------------- ; Get DPMI information before doing anything 386-specific - push es push di - xor cx, cx ; flag for load attempt set cx = 0 - jz @f2 ; We always jump, shorter than jmp + ; Set up loadname in case of no DPMI. + ; First try current dir. + xor ah, ah ; Copy until this character (=0) + call store_env_string ; copy stub image to "loadname" + mov si, bx ; remove name so we can add DPMI name + mov di, [path_off] ; Pointer to path contents (next try) @b1: + xor cx, cx ; flag to signal end of loop +@b2: + call check_dpmi ; int 2f, ax=1687 + jz @f3 + call do_exec ; copy our name to string and try load + jcxz @f1 ; cx=0 while we have more paths to try + call check_dpmi ; last chance... + jz @f3 mov al, 110 mov dx, msg_no_dpmi jmpl error -@b2: - or cx, cx - jnz @b1 ; we already tried load once before - inc cx - call load_dpmi - jc @b1 +@f1: + ; Set up loadname for next attempt. + mov ah, ';' ; Copy until this character + call store_env_string ; to "loadname" + or al, al ; Check terminating character + jne @f2 ; If ';', continue + dec di ; else point at null for next pass. @f2: - mov ax, 0x1687 ; get DPMI entry point - int 0x2f - or ax, ax - jnz @b2 ; if 0 then it's there - and bl, 1 ; 32 bit capable? - jz @b2 + inc cx + cmp si, loadname ; anything there? + je @b2 ; final try (no path) + mov al, [si-1] + call test_delim ; is final character a path delimiter + je @b1 + movb [si], '\\' ; no, add separator between path & name + inc si + jmp @b1 @f3: - mov [modesw], di ; store the DPMI entry point - mov [modesw+2], es - mov [modesw_mem], si pop di - pop es ;----------------------------------------------------------------------------- ; Now, find the name of the program file we are supposed to load. -; xor ah, ah ; termination character (set above!) +; xor ah, ah ; termination char (set by check_dpmi) call store_env_string ; copy it to loadname, set bx mov [stubinfo_env_size], di @@ -700,36 +711,29 @@ pm_dos: ret ;----------------------------------------------------------------------------- -; load DPMI server if not present -; First check directory from which stub is loaded, then path, then default -; On entry di points to image name +; Check for presence of a DPMI host, and save the mode switch address. +; Zero flag is clear on success. Clobbers ax/bx/dx. -path_off: - .dw 0 ; If stays zero, no path - -load_dpmi: - xor ah, ah ; Copy until this character (=0) - call store_env_string ; copy stub image to "loadname" - mov si, bx ; remove name so we can add DPMI name - mov di, [path_off] ; Pointer to path contents (next try) - jmp @f2 -loadloop: - mov ah, ';' ; Copy until this character - call store_env_string ; to "loadname" - or al,al ; Check terminating character - jne @f1 ; If ';', continue - dec di ; else point at null for next pass. -@f1: - cmp si, loadname ; anything there? - je do_exec ; final try (no path) let it return - mov al, [si-1] - call test_delim ; is final character a path delimiter - je @f2 - movb [si], '\\' ; no, add separator between path & name - inc si -@f2: - call do_exec ; copy our name to string and try load - jc loadloop +check_dpmi: + push es + push cx + push di + push si + mov ax, 0x1687 ; get DPMI entry point + int 0x2f + mov dx, bx + or dl, 1 ; bx bit 0: 32-bit capable + xor bx, dx + or ax, bx ; DPMI present if ax = 0 + jnz @f1 + mov [modesw], di ; store the DPMI entry point + mov [modesw+2], es + mov [modesw_mem], si +@f1: + pop si + pop di + pop cx + pop es ret ;----------------------------------------------------------------------------- @@ -766,13 +770,6 @@ do_exec: int 0x21 pop di pop es - jc @f1 ;carry set if exec failed - - mov ah, 0x4d ;get return code - int 0x21 - sub ax, 0x300 ;ah=3 TSR, al=code (success) - neg ax ;CY, if not originally 0x300 -@f1: jmp restore_umb ;called func. return for us. ;----------------------------------------------------------------------------- @@ -796,10 +793,9 @@ include_umb: @f1: ret -; Restore upper memory status. All registers and flags preserved. +; Restore upper memory status. All registers preserved. restore_umb: - pushf cmpb [dos_major], 5 ; Won't work before dos 5 jb @f1 push ax @@ -815,7 +811,6 @@ restore_umb: pop bx pop ax @f1: - popf ret ;----------------------------------------------------------------------------- @@ -840,6 +835,8 @@ msg_no_selectors: .db "no DPMI selectors$" msg_no_dpmi_memory: .db "no DPMI memory$" +path_off: + .dw 0 ; Points to PATH, stays zero if none. ;----------------------------------------------------------------------------- ; Unstored Data, available during and after mode switch