rosegondon
C:\DOS, 14.01.2022, 22:39 |
How to detect FreeDOS kernel from Turbo Pascal program? (Developers) |
Hello,
I am looking for a method of detection of running FreeDOS kernel from Turbo Pascal compiled program. Because under FreeDOS various shells can be loaded (for example FreeCOM can be replaced by 4DOS) this cannot be a method referring to simple shell call. What I need is to find if my Pascal program runs under FreeDOS kernel, regardless of the command interpreter used.
For now I use ugly and dirty code of type "if exist {boot drive}\kernel.sys then RunningUnderFreeDOS" but this ugliness fails miserably when multiboot (and multikernel) configuration is working because while kernel.sys is present, it doesn't mean it is loaded. --- echo g=ffff:0|debug>nul |
mceric
Germany, 15.01.2022, 00:22
@ rosegondon
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> I am looking for a method of detection of running FreeDOS kernel
set ax=0x3000 and call int 0x21, check whether the returned bh is 0xfd.
if yes, set ax=0x33ff and call int 0x21, it returns a pointer dx:ax to a version string.
how to express this in the programming language of your choice is up to you, please share an example implementation code snippet here --- FreeDOS / DOSEMU2 / ... |
Oso2k
15.01.2022, 00:24
@ rosegondon
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> Hello,
>
> I am looking for a method of detection of running FreeDOS kernel from Turbo
> Pascal compiled program. Because under FreeDOS various shells can be loaded
> (for example FreeCOM can be replaced by 4DOS) this cannot be a method
> referring to simple shell call. What I need is to find if my Pascal program
> runs under FreeDOS kernel, regardless of the command interpreter used.
>
> For now I use ugly and dirty code of type "if exist {boot
> drive}\kernel.sys then RunningUnderFreeDOS" but this ugliness fails
> miserably when multiboot (and multikernel) configuration is working because
> while kernel.sys is present, it doesn't mean it is loaded.
http://www.ctyme.com/intr/rb-2711.htm
http://www.ctyme.com/intr/rb-2730.htm |
Laaca
Czech republic, 15.01.2022, 11:09 (edited by Laaca, 15.01.2022, 11:23)
@ rosegondon
|
How to detect FreeDOS kernel from Turbo Pascal program? |
The DOS call proposed by McEric certainly works but I recommend to use a shell call. The "ver" command is reliable and the format should be standardised even through various alternate command interpretters.
Firstly call simply "ver".
Then, if it contains string "FREECOM" (after capitalization) call "ver /r" and analyse the output. --- DOS-u-akbar! |
mceric
Germany, 15.01.2022, 12:29
@ Laaca
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> The DOS call proposed by McEric certainly works but I recommend to use a
> shell call. The "ver" command is reliable and the format should be
> standardised even through various alternate command interpretters.
I disagree. I am not aware of any standard format for the text returned by a VER shell command in the DOS wild west.
Also, calling the shell and interpreting the results is a lot more overhead than calling a well-documented int 21.30 kernel interface or even a less documentet FreeDOS kernel version string interface. Also note that only FreeCOM, but not non-FreeDOS shells, is able to include the kernel version string in the VER /R output. The normal VER output only shows the version of FreeCOM, not the version of FreeDOS, and you can use FreeCOM with any version of DOS, possibly not FreeDOS at all.
By the way, I am curious why the Turbo Pascal program wants to know whether a FreeDOS kernel is active, does it need any special workarounds? Or does it provide extra features that you want to detect to be present? --- FreeDOS / DOSEMU2 / ... |
rosegondon
C:\DOS, 15.01.2022, 16:20 (edited by rosegondon, 15.01.2022, 16:39)
@ mceric
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> > I am looking for a method of detection of running FreeDOS kernel
>
> set ax=0x3000 and call int 0x21, check whether the returned bh is 0xfd.
>
> if yes, set ax=0x33ff and call int 0x21, it returns a pointer dx:ax to a
> version string.
>
> how to express this in the programming language of your choice is up to
> you, please share an example implementation code snippet here
Success! It works even when FreeCOM is not used at all.
Uses Dos;
Function IsFreeDos : Boolean;
VAR Regs : Registers;
begin
With Regs do
begin
ax := $3000;
bx := $00;
end;
Intr ($21, Regs);
if Regs.bh = $FD then IsFreeDOS := TRUE else IsFreeDOS := FALSE
end;
Begin
WriteLn(IsFreeDos);
End. --- echo g=ffff:0|debug>nul |
ecm
Düsseldorf, Germany, 15.01.2022, 17:32
@ mceric
|
21.33FF kernel version string interface |
> > I am looking for a method of detection of running FreeDOS kernel
>
> set ax=0x3000 and call int 0x21, check whether the returned bh is 0xfd.
>
> if yes, set ax=0x33ff and call int 0x21, it returns a pointer dx:ax to a
> version string.
>
> how to express this in the programming language of your choice is up to
> you, please share an example implementation code snippet here
Here's an example for the latter call in 8086 NASM assembly: callver.asm
mov ax,33ffh ; get FreeDOS version string pointer
xor dx, dx
int 21h ; returns DX AX
test dx, dx
jnz gotname
mov dx, ds
mov ax, msgnoname
The returned pointer is an ASCIZ string that may have trailing whitespace (such as CR or LF). There is some code following the quoted part that will ignore trailing whitespace.
Here's an addition I made to comcom32, a DPMI client shell written in C. It does essentially the same as my callver code: Preset dx to zero, check for a nonzero return in dx, and ignore trailing whitespace. (It also ignores leading whitespace and copies the entire string to a 256-byte buffer allocated by malloc.)
Here's the same function in RxCMD, 8086 assembly too.
Crucially this doesn't depend on the 21.3000 OEM number (like a prior version of callver) to detect support for the 21.33FF function. Instead, it presets dx to zero and checks for a non-zero segment return. This function is also supported by my more recent RxDOS kernels (which have OEM number 5Eh).
Here's the string in RxDOS's DOS code segment: https://hg.pushbx.org/ecm/rxdos-7.2x/file/38ec35f277df/RxDOS/doscode.asm#l58
Here's what it looks like in the file: (from the uncompressed RxDOS.COM file of RxDOS version 7.24)
001B90 0C 0C 0C 0C 0C 0C 0C 04-04 52 78 44 4F 53 20 76 >.........RxDOS v<
001BA0 65 72 73 69 6F 6E 20 37-2E 32 34 20 5B 68 67 20 >ersion 7.24 [hg <
001BB0 62 30 30 34 65 61 38 30-65 32 32 32 5D 20 5B 32 >b004ea80e222] [2<
001BC0 30 31 38 2D 31 30 2D 30-39 5D 00 5E 43 0D 0A 00 >018-10-09].^C...<
This is the result of using the call on my current FreeDOS in dosemu2 setup:
C:\>ldebug
-a
1E8E:0100 mov ax, 33ff
1E8E:0103 int 21
1E8E:0105 nop
1E8E:0106
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=1E8E ES=1E8E SS=1E8E CS=1E8E IP=0100 NV UP EI PL ZR NA PE NC
1E8E:0100 B8FF33 mov ax, 33FF
-t
AX=33FF BX=0000 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=1E8E ES=1E8E SS=1E8E CS=1E8E IP=0103 NV UP EI PL ZR NA PE NC
1E8E:0103 CD21 int 21
-
AX=17E4 BX=0000 CX=0000 DX=00D9 SP=FFFE BP=0000 SI=0000 DI=0000
DS=1E8E ES=1E8E SS=1E8E CS=1E8E IP=0105 NV UP EI PL ZR NA PE NC
1E8E:0105 90 nop
-d dx:ax
00D9:17E0 46 72 65 65-44 4F 53 20 6B 65 72 6E FreeDOS kern
00D9:17F0 65 6C 20 2D 20 47 49 54-20 28 62 75 69 6C 64 20 el - GIT (build
00D9:1800 32 30 34 33 20 4F 45 4D-3A 30 78 66 64 29 20 5B 2043 OEM:0xfd) [
00D9:1810 63 6F 6D 70 69 6C 65 64-20 4F 63 74 20 32 38 20 compiled Oct 28
00D9:1820 32 30 32 31 5D 0A 00 00-68 93 68 93 68 93 68 93 2021]...h.h.h.h.
00D9:1830 BD 94 BD 94 68 93 68 93-BD 94 BD 94 68 93 51 93 ....h.h.....h.Q.
00D9:1840 68 93 BD 94 BD 94 BD 94-68 93 00 00 03 0C 03 0C h.......h.......
00D9:1850 06 0A 0F 00 00 00 13 13-17 18 19 19 22 5B 5D 3A ............"[]:
00D9:1860 7C 3C 3E 2B - |<>+
-
Note the trailing 0Ah byte (Line Feed). --- l |
rosegondon
C:\DOS, 17.01.2022, 20:06
@ ecm
|
21.33FF kernel version string interface |
> > > I am looking for a method of detection of running FreeDOS kernel
> >
> > set ax=0x3000 and call int 0x21, check whether the returned bh is 0xfd.
> >
> > if yes, set ax=0x33ff and call int 0x21, it returns a pointer dx:ax to a
> > version string.
> >
> > how to express this in the programming language of your choice is up to
> > you, please share an example implementation code snippet here
>
> Here's an example for the latter call in 8086 NASM assembly:
> callver.asm
>
>
> mov ax,33ffh ; get FreeDOS version string pointer
> xor dx, dx
> int 21h ; returns DX AX
> test dx, dx
> jnz gotname
> mov dx, ds
> mov ax, msgnoname
>
>
> The returned pointer is an ASCIZ string that may have trailing whitespace
> (such as CR or LF). There is some code following the quoted part that will
> ignore trailing whitespace.
How to get this version string in Pascal? --- echo g=ffff:0|debug>nul |
DosWorld
18.01.2022, 02:54
@ rosegondon
|
21.33FF kernel version string interface |
> How to get this version string in Pascal?
:)
function GetFreeDosVer : pchar; assembler;
asm
> > mov ax,$33ff ; get FreeDOS version string pointer
> > xor dx, dx
> > int $21 ; returns DX AX
> > test dx, dx
> > jnz @gotname
xor ax, ax
mov dx, ax
@gotname:
end; --- Make DOS great again!
Carthago delenda est, Ceterum censeo Carthaginem delendam esse. |
rosegondon
C:\DOS, 18.01.2022, 09:06
@ DosWorld
|
21.33FF kernel version string interface |
> > How to get this version string in Pascal?
>
> :)
>
> function GetFreeDosVer : pchar; assembler;
> asm
> > > mov ax,$33ff ; get FreeDOS version string pointer
> > > xor dx, dx
> > > int $21 ; returns DX AX
> > > test dx, dx
> > > jnz @gotname
> xor ax, ax
> mov dx, ax
> @gotname:
> end;
Uses Strings;
Begin
Writeln(StrPas(GetFreeDosVer));
End.
Under MS-DOS this function returns a string of random characters. Shouldn't it return empty result under DOS other than FreeDOS? --- echo g=ffff:0|debug>nul |
Laaca
Czech republic, 18.01.2022, 14:25
@ rosegondon
|
21.33FF kernel version string interface |
Or this dualistic implementation (Turbopascal / Freepascal)
(compatible with both FPC calling modes: oldfpccall and fastcall)
Procedure Get_FreeDOS_version_string_asm(var s,o:word);assembler;
asm
{$IFDEF FPC}
push esi
push edi
mov esi,s
mov edi,o
mov ax,33ffh
mov dx,0
int 21h
mov [esi],dx
mov [edi],ax
pop edi
pop esi
{$ELSE}
push si
push ds
mov ax,33ffh
mov dx,0
int 21h
lds si,s
mov [si],dx
lds si,o
mov [si],ax
pop ds
pop si
{$ENDIF}
end;
Function Get_FreeDOS_version_string:string;
var t:string;
s,o:word;
a,b:byte;
begin
Get_FreeDOS_version_string_asm(s,o);
t:='';
if s<>0 then
for a:=0 to 254 do
begin
b:=Mem[s:o+a];
if b=0 then break else
if b>=32 then t:=t+char(b);
end;
Get_FreeDOS_version_string:=t;
end;
begin
writeln(Get_freedos_version_string);
end. --- DOS-u-akbar! |
tkchia
18.01.2022, 15:30
@ rosegondon
|
21.33FF kernel version string interface |
Hello rosegondon,
> > function GetFreeDosVer : pchar; assembler;
> > asm
> > > > mov ax,$33ff ; get FreeDOS version string pointer
> > > > xor dx, dx
> > > > int $21 ; returns DX AX
> > > > test dx, dx
> > > > jnz @gotname
> > xor ax, ax
> > mov dx, ax
> > @gotname:
> > end;
>
> Uses Strings;
> Begin
> Writeln(StrPas(GetFreeDosVer));
> End.
>
> Under MS-DOS this function returns a string of random characters. Shouldn't
> it return empty result under DOS other than FreeDOS?
The above implementation under MS-DOS will return a null pointer (0:0) — which in general may not point to an empty string. You probably want to check that the returned pointer is not a null pointer.
Thank you! --- https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI" |
DosWorld
18.01.2022, 16:44
@ rosegondon
|
21.33FF kernel version string interface |
> Writeln(StrPas(GetFreeDosVer));
(TP's) "Writeln" can write content from pchar.
PS: (To rosegondon)
var str :pchar;
begin
str := GetFreeDosVer;
if str <> nil then Writeln(str);
end. --- Make DOS great again!
Carthago delenda est, Ceterum censeo Carthaginem delendam esse. |
Laaca
Czech republic, 18.01.2022, 19:06
@ mceric
|
How to detect FreeDOS kernel from Turbo Pascal program? |
By the way, where is documented the INT21h/AX=33FFh?
I am looking at the Ralf Brown's interrupt list and don't see it there...
It is even not mentioned nowhere on the FreeDOS site, what is shame... --- DOS-u-akbar! |
rosegondon
C:\DOS, 18.01.2022, 19:14
@ DosWorld
|
21.33FF kernel version string interface |
> > Writeln(StrPas(GetFreeDosVer));
>
> (TP's) "Writeln" can write content from pchar.
>
> PS: (To rosegondon)
> var str :pchar;
> begin
> str := GetFreeDosVer;
> if str <> nil then Writeln(str);
> end.
@Laaca, @DosWorld - thank you!
I acquired your code and it works perfectly. Thank you for FreePascal version! --- echo g=ffff:0|debug>nul |
Rugxulo
Usono, 19.01.2022, 00:57
@ Laaca
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> By the way, where is documented the INT21h/AX=33FFh?
> I am looking at the Ralf Brown's interrupt list and don't see it there...
>
> It is even not mentioned nowhere on the FreeDOS site, what is shame...
It's mentioned (at least by Eric) as far back as 2005:
"[Freedos-devel] re: re: VER /R" (2005-07-29)
So see the kernel sources:
VOID ASMCFUNC int21_syscall(iregs FAR * irp)
...
switch (irp->AH)
...
case 0x33:
switch (irp->AL)
...
/* set FreeDOS returned version for int 21.30 from BX */
case 0xfc: /* 0xfc ... 0xff are FreeDOS extensions */
os_setver_major = irp->BL;
os_setver_minor = irp->BH;
break;
...
/* Get DOS-C release string pointer */
case 0xff:
irp->DX = FP_SEG(os_release);
irp->AX = FP_OFF(os_release);
}
break;
...
I had my own wimpy code from 2007, so clearly I learned it from somebody:
LANG OCTASM,0.1
org 100h use16 file_out \whatfdos.com
VER=33FFh
#Komenco ax=VER int 21h jc Fino cmp ax,VER jz Fino
ds=dx si=ax ax=1225h int 2Fh # lodsb int 29h loop <1
#Fino ret
|
Rugxulo
Usono, 19.01.2022, 01:05
@ rosegondon
|
How to detect FreeDOS kernel from Turbo Pascal program? |
> Success! It works even when FreeCOM is not used at all.
Minor improvements:
program whatfdos;
uses DOS;
function IsFreeDOS: boolean;
var reg: registers;
begin
reg.ax := $3000; reg.bx := 0;
msdos(reg);
IsFreeDOS := reg.bh = $FD
end;
begin
writeln('FreeDOS = ',IsFreeDOS)
end.
|
Laaca
Czech republic, 19.01.2022, 10:33
@ Rugxulo
|
How to detect FreeDOS kernel from Turbo Pascal program? |
I would not consider a code snippet mentioned a year ago in some email conversation as a properly documented FreeDOS function
The all FreeDOS webpage is awful but it would be for an another topic. Anyway, there is nowhere mentioned this function call.
I know - in the main menu is "Links", and there a section "technical documentation". There are about 3 copies of RBIL and some other stuff.
But INT21h/AX=33FFh? Nowhere. --- DOS-u-akbar! |