Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

int20 should take PSP from CS #185

Open
stsp opened this issue Oct 12, 2021 · 14 comments
Open

int20 should take PSP from CS #185

stsp opened this issue Oct 12, 2021 · 14 comments

Comments

@stsp
Copy link
Member

stsp commented Oct 12, 2021

Currently int20 terminates current PSP
instead of the one in CS. Hope no one
cares, this is a minor bug.
Same with freedos.

@stsp
Copy link
Member Author

stsp commented Oct 12, 2021

Same for int27.

@andrewbird
Copy link
Member

Is this something we should test across all the DOS variants? Did you find out with a testcase or by studying the code?

@stsp
Copy link
Member Author

stsp commented Oct 12, 2021

By studying the code.
int20_handler() and int27_handler()
just pass to int21.
Test would be cool.

@andrewbird
Copy link
Member

Mmm, isn't int27 a strange one. Thinking about how to test this, I figure I have to do the following

1/ resize (int21/4a) myself to leave space for a new allocation
2/ allocate a new some space(int21/48)
3/ build a new PSP there. (what's the minimum requirement?)
4/ copy in some minimal code to run
5/ far jump to it
6/ TSR (int27)

But I wonder how to test from DOS afterwards which program is resident, and what was released?

@stsp
Copy link
Member Author

stsp commented Oct 12, 2021

I think the easiest is to have a
com file. First, it loads itself via 4b
one but sets the "no execute" mode.
But it will create&change PSP.
Then you get PSP with 62h and
compare it with CS:

AX=4b01;
do_int21();
if (PSP == CS) {
    printf("Test FAILED\n");
    exit(1);
} else {
    /* we are on child PSP now */
    do_int20();
    /* no return */
}

This is all.
So if PSP is child's, we execute int20.
If it ignored the current PSP and looked
up CS, then we immediately exit to
command.com with 0 exit code. This
should be a correct behavior (but the
child's com file will be leaked - maybe
you can improve the test to avoid mem
leak). But if it instead terminated child's
PSP, then we return from do_int21() for
the second time and PSP now matches
CS, which we detect.

@stsp
Copy link
Member Author

stsp commented Oct 12, 2021

Even simpler is to just use the
static variable to count the number
of times you returned from do_int21():

AX=4b01;
do_int21();
if (cnt++ == 0)
    do_int20();
else
    printf("Test FAILED\n");

@andrewbird
Copy link
Member

No sure I get it fully yet, but I'll experiment with it later when I return home. Thanks for the ideas!

@ecm-pushbx
Copy link

Interrupt 21h function 00h has the same behaviour as int 20h in MS-DOS, I believe. (You can look at the MIT-licensed MS-DOS version 2 sources.)

@stsp
Copy link
Member Author

stsp commented Oct 12, 2021

Yes, good point.
Indeed freedosish asm replaces
int20 with int21/00, and later the
C code does another morphing:

      /* Terminate Program                                            */
    case 0x00:
      lr.AX = 0x4c00;
    
      /* End Program                                                  */
    case 0x4c:

Unfortunately, checking CS breaks
the progs under debugger. For that
reason we already stopped checking
CS in int21/26h.
I suppose we should stop adding an
extra stack frames with the debugger
and just use the breakpoint instead.
I believe Andrew worked on something
like that already?

@andrewbird
Copy link
Member

I believe Andrew worked on something
like that already?

Yes I just found that old local branch, amusingly the final commit in the series was called 'crap commit - about to give up`. So there's probably nothing of value there! 😄

@tkchia
Copy link
Contributor

tkchia commented Jul 15, 2022

Hello @stsp, @ecm-pushbx, @andrewbird,

Arrrgh. My understanding is that both int 0x20 and int 0x21 function 0x00 kind of assume that cs points to the current PSP. int 0x21 function 0x4c does not, though, which is why it can be called from anywhere in conventional memory.

Are there actually any real-life programs that try to pull a fast one, and invoke int 0x20 (or int 0x21, ah = 0) with cs ≠ current PSP? 🤔

@stsp
Copy link
Member Author

stsp commented Jul 15, 2022

Hope there is none.
Which is why fixing this "bug"
is not very tempting. :)
But certainly a test can be
written that reveals an
"incompatibility".

@tkchia
Copy link
Contributor

tkchia commented Jul 15, 2022

Hello @stsp,

Which is why fixing this "bug" is not very tempting. :)

Me, I have half a mind to make the kernel complain "lolwut, your program is doing something bogus!" when some program calls int 0x20 with cs ≠ PSP...

Thank you!

@stsp
Copy link
Member Author

stsp commented Jul 15, 2022

This can't work because int21 can
be hooked. In that case you may
see CS of a hooker on stack.
Also debugger may put an additional
iret frame...
Overall checking CS is a PITA, and
especially not worth a trouble just as
a sanity check.
Right now fdpp simply uses current
psp, and that is obviously the Right Thing
(tm), except that MS-DOS does otherwise.

stsp added a commit that referenced this issue Oct 14, 2023
int21/26h under ms-dos uses CS instead of current_psp.
This is quite bad, but AlphaWaves is not going to work otherwise.

See also #185
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants