Open stsp opened 3 years ago
Same for int27.
Is this something we should test across all the DOS variants? Did you find out with a testcase or by studying the code?
By studying the code. int20_handler() and int27_handler() just pass to int21. Test would be cool.
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?
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.
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");
No sure I get it fully yet, but I'll experiment with it later when I return home. Thanks for the ideas!
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.)
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?
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! :smile:
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? :thinking:
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".
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!
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.
Currently int20 terminates current PSP instead of the one in CS. Hope no one cares, this is a minor bug. Same with freedos.