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=20230601; t=1709055341; x=1709660141; darn=delorie.com; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=zUnc5HlP+8ICf4po0SxcW/ZK6ctKUwopyXM1QfoLx2U=; b=AXVQQ3ZFDO5V3f099fxAgby17Kot2PBEo4OQX16iFPt1lh5tff8HY/PU5JaJY0GCUo VaMhkoQttsIXzr5b7jD0dccS9Ydq00NQs4qbw1oK74IqQWutbRytxFymZqEyN/VnkS1j dQ+JIEBa/IZWx9u2FnF0hDmKMuBKPYlL8Oq6gzKV40RkwjBy4X2oyBGWJawz+ZxoGYzj SKj43aZQ049i1Pf/Qr8WP/XwfD7efkV5HuX7xHLDFUlOTybN54S+Tz6xNHHYEAqPzvOB ERwI0c7RlqIHqrgV1Xa2HaK4AQ4GaCn7xbLMBq499minhxGgDoH8HI7rZx8mVvrsLQe/ 6sDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709055341; x=1709660141; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zUnc5HlP+8ICf4po0SxcW/ZK6ctKUwopyXM1QfoLx2U=; b=f/QQCBnn7UzeQ+/ywLCLYqdvQzbLKOdlFM5XZkAwuMMk5BtANlq8S4BGIdR5NKhCLF haotK1UxGV+hZIVR5natkjaoZ/tVwb+enL+lEiCxGRSBwBf1t4eE0cEP3XB0D24+UnyJ ztU4xQONpe1XW0xvOdB0zfpexUq2uaagLTY9+bKdFaRosDbuuI1rOK4I8jio5OCcLgr/ vBgmimH5kZGmv2YXxB7hDyWZQXNq57D1PY9uyS/bjmGPAq1rLCOGAtlS6qWoJI6gmMQM /7Rav16sMtFp05zyrHkrIrF4b4oCqdzXAfGwRsHw9h1NxnO2W9D0OsPD8Ltd/N3LylM4 ITXg== X-Gm-Message-State: AOJu0YxvAoEueWOgyqI4KcTmK1I7S8PCZ9qyxS1PrlHVSHJO4314TW3/ uKB7S/oQqJRg8Lr6Pm/A5ofIru71ThDzD/2V02+Sm+g2znpokHTnbKZ6UcZbzpTgqseeIbeY3sR s3tfI9SoEMxiZD6tIFUpbsmJTI97Ycj2W X-Google-Smtp-Source: AGHT+IETpRYCO+XUGflVBvGQ+AzT0ZPZhyIZQ7Bpk90qzP0D7Wm3CDkVUltKLYHRGW8dUqSMEbohJl4VvY3G+pxG0MI= X-Received: by 2002:a05:6000:12d0:b0:33d:6554:fe81 with SMTP id l16-20020a05600012d000b0033d6554fe81mr6907699wrx.64.1709055340960; Tue, 27 Feb 2024 09:35:40 -0800 (PST) MIME-Version: 1.0 References: <744f054f-9682-4a05-91ad-684b18c0122b AT gmail DOT com> <21e1aa0b-1511-0071-84c0-b20c6a3d1dae AT gmail DOT com> <5de28b44-10f2-c824-def1-d451035ecaad AT gmail DOT com> In-Reply-To: <5de28b44-10f2-c824-def1-d451035ecaad@gmail.com> From: "Ozkan Sezer (sezeroz AT gmail DOT com) [via djgpp AT delorie DOT com]" Date: Tue, 27 Feb 2024 20:35:29 +0300 Message-ID: Subject: Re: [PING][PATCH v2] stub: ignore host exit status To: djgpp AT delorie DOT com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id 41RHZgGl1028179 Reply-To: djgpp AT delorie DOT com On Wed, Jan 25, 2023 at 12:56 AM J.W. Jagersma (jwjagersma AT gmail DOT com) [via djgpp AT delorie DOT com] wrote: > > Would appreciate any feedback on this. I know there's a small mistake in one > comment, but the code works. > > On 2022-11-25 00:26, J.W. Jagersma wrote: > > 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 > > > PING? Has anyone reviewed this one?