VOGONS


First post, by videogamer555

User metadata
Rank Member
Rank
Member

I'm planning to write my own program that switches into 32bit protected mode, and I want to make sure DosBox will run it properly. However, to do this, I need to first switch on the A20 memory address line. According to http://www.independent-software.com/ope ... -line.html there are 3 techniques to do this, and not every technique works with every computer. Which of these techniques does DosBox support?

Reply 2 of 20, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

The method also depends on if dosbox is running and dpmi server or vcpi server as well. The A20 may already be on if HMA is used as well.

unless your booting through a boot sector then none of those is probably relevant, but some BIOS will enable A20 automatically (if you get to the point of using your app on a real machine.)

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: mega-tokyo.com ]-/\--

Reply 3 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
jmarsh wrote on 2020-01-15, 01:24:

It supports it via the keyboard controller and port 92, it doesn't support int15 function 24 but will enable A20 during int 15 function 89 (switch to protected mode).

INT15 function 89 (and is this decimal 89, or hex 0x89) can perform a switch to protected mode? Is that just a DOSBox feature? Or do real BIOS's do that to? I remember thinking I needed to set a control register in the CPU to do that via something like MOV CR0,AX in assembly, after setting register AX to the value that will switch the CPU into protected mode once that value is placed in the control register.

Reply 5 of 20, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie
videogamer555 wrote on 2020-01-17, 04:57:

I remember thinking I needed to set a control register in the CPU to do that via something like MOV CR0,AX in assembly, after setting register AX to the value that will switch the CPU into protected mode once that value is placed in the control register.

setting protected mode via CR0 only works if the system is not already in protected mode. (ie: emm386, vcpi, dpmi, v86)

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: mega-tokyo.com ]-/\--

Reply 6 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
BloodyCactus wrote on 2020-01-17, 13:20:
videogamer555 wrote on 2020-01-17, 04:57:

I remember thinking I needed to set a control register in the CPU to do that via something like MOV CR0,AX in assembly, after setting register AX to the value that will switch the CPU into protected mode once that value is placed in the control register.

setting protected mode via CR0 only works if the system is not already in protected mode. (ie: emm386, vcpi, dpmi, v86)

Interesting. CR0 is the method I've always seen in online ASM tutorials for going into protected mode. I've never seen INT15 function 89 mentioned before. So that INT15 function 89 works on real hardware too then, not just DOSBox? How about A20 becoming enabled when calling INT15 function 89? Is that also something that happens on real hardware, or is that only in DOSBox?

If possible, I'd like my software to be able to do this on real hardware, with DOSBox only being used as a tester/debugger for my program. And I know that DOSBox has a lot of optimizations that make it behave not quite like real hardware (which is why it's mentioned in this forum that it's only for games and not normal applicaitons).

Reply 7 of 20, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

Ive written a dos exetender. going into pmode is a lot of work once you take all the things into account.
Setting the bit in CR0 is easy, but you cant do that if people have emm386 loaded or qemm etc. So many things! I've never used INT 15. I detect vcpi/dpmi/xms/raw methods.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: mega-tokyo.com ]-/\--

Reply 8 of 20, by jmarsh

User metadata
Rank Member
Rank
Member

It's a standard AT bios function.
Keep in mind the bios isn't magic, it just contains a bunch of x86 subroutines. The function doesn't do anything that your program couldn't implement directly, and will trigger the same exceptions if the CPU is already running protected.

Reply 9 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
jmarsh wrote on 2020-01-18, 01:45:

It's a standard AT bios function.
Keep in mind the bios isn't magic, it just contains a bunch of x86 subroutines. The function doesn't do anything that your program couldn't implement directly, and will trigger the same exceptions if the CPU is already running protected.

I'm trying to create a program, which uses 32bit instructions for processing information 32bits at a time. I could use 32bit instructions in 16bit real mode, but that is slow because of the 0x66 prefix before every 32bit instruction. My processing will be done in loops to process all the data, and any delay caused by the 0x66 prefix will be multiplied by the number of times the loop runs (which will be a lot). Also, switching to 32bit mode will give me full access to system memory (I think I have 4 gigs of ram in my PC) instead of just 1MB as in 16bit real mode, and with the amount of data I'm going to process I will need far more than 1MB. Why not just write a Windows program? Inaccuracy (jitter) of the Windows timer. A "15ms delay" one time around may be 14ms during one iteration, but 16ms the next. A workaround is using low level access in ring0 mode to directly communicate with PC's hardware timer, but Windows blocks applications from using ring0 mode. Even if I could, because instructions execute when Windows wants to allow it (task scheduler kernel feature in Windows), one run through a loop may take 0.10us in the first iteration but 0.12us the next iteration. So I need to run my program separate from Windows. Yes, DOSBox is running in Windows, with all its restrictions, but I'm only using DOSBox to test the program, to see if it will run at all.

My plan is for my program to run in 32bit protected mode, ring0. The idea for the final use of my program will be I will have a USB disk with DOS installed, and a copy of my program. I will boot the USB drive, run my program, which will then switch to 32bit protected mode ring0, and load the data file from disk (or an external sensor connected to serial port or even USB port). It will then process the data and save it to another file. When I want the processing stopped, I have no intent to go through the complexities of writing a program that backs out of 32bit protected mode, so shutting off the program is quite simple. Just power off the computer. Then to go back to Windows, just unplug the USB drive and power the computer back on, and Windows will boot from the normal internal harddrive.

Since timing precision and accuracy (no jitter) for live high-speed signal processing is needed for my application, running a dedicated program which runs from DOS and switches itself into 32bit protected mode is absolutely necessary (unlike most 32bit programs, which run from an OS that has already switched into 32bit protected mode). Having the overhead of a multitasking OS (such as Windows, or even any version of Linux with a GUI) which does stuff like task scheduling, that messes up the timing of the program you are running, is absolutely not an option in my case.

Reply 10 of 20, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

0x66 is not a time consuming prefix. just write it in C and use inline assembler with Watcom or DJGPP and get a protected mode 32bit app without the hassle of setting up GDT, LDT, IDT and exception, MMU and page tables. that way nothing is running but your task, in protected mode.

if your stuff is so cycle intensive, your doing it wrong trying to go into protected mode via dos.

GPU processing exists for a reason.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: mega-tokyo.com ]-/\--

Reply 11 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
BloodyCactus wrote on 2020-01-18, 20:36:

0x66 is not a time consuming prefix. just write it in C and use inline assembler with Watcom or DJGPP and get a protected mode 32bit app without the hassle of setting up GDT, LDT, IDT and exception, MMU and page tables. that way nothing is running but your task, in protected mode.

if your stuff is so cycle intensive, your doing it wrong trying to go into protected mode via dos.

GPU processing exists for a reason.

Are there any versions of C for Windows that can compile for DOS? The convenience of running the compiler in Windows, instead of having to use DOSBox for compiling the program in the first place, would be nice. I already am using the assembler NASM to write my DOS programs in Windows, because of the convenience of compiling in Windows, and then running it in DOSBox via the command line "dosbox-debugger.exe myprogram.com".

As for GPU processing, you saying GPU processing can be done in DOS? If not, how do you do it in Windows? (though this is off topic and should probably be in a different thread)

Reply 12 of 20, by videogamer555

User metadata
Rank Member
Rank
Member

If using the int 0x15 function 0x89 method to switch to protected mode, it seems that the GDT is in a different format than normal. Normally you can set up your GDT with as many segments as you want, and then load it with the instruction LGDT. However, it seems to work a bit differently with int 0x16 function 0x89. It seems to expect exactly 8 entries (including the first null entry), and each entry seems to be for a specific purpose. However, when researching what the purpose of each GDT entry is, it seems there is a bit of disagreement between different websites as to just what the exact layout is for this int15 BIOS GDT. Also, there's not too many websites that seem to carry this information. I found only 2 so far in my research, and they definitely are not in agreement about the proper layout of this table. Here are the 2 sites I found.
http://staff.ustc.edu.cn/~xyfeng/resear ... y/gdt.html
http://www.oldlinux.org/Linux.old/docs/ ... b-1531.htm

Hopefully some DOSBox developers can shed some light on this, and let me know the actual correct layout of the BIOS GDT for int 0x15 function 0x89.

Reply 14 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
jmarsh wrote on 2020-01-19, 01:06:

The first site is describing the GDT layout for function 87, not 89.

DOH! Sorry, I misread that. I was Googling for help on int 0x15 function 0x89 and just assumed that what Google gave me was correct.

Reply 15 of 20, by videogamer555

User metadata
Rank Member
Rank
Member

In here http://www.oldlinux.org/Linux.old/docs/ ... b-1531.htm the layout of the GDT is stated as follows.

Format of BIOS switch-to-protected-mode Global Descriptor Table:

Offset Size Description (Table 00500)
00h 8 BYTEs null descriptor (initialize to zeros)
08h 8 BYTEs GDT descriptor (see #00501)
10h 8 BYTEs IDT descriptor
18h 8 BYTEs DS descriptor
20h 8 BYTEs ES
28h 8 BYTEs SS
30h 8 BYTEs CS
38h 8 BYTEs uninitialized, used to build descriptor for BIOS CS

I've got some questions about that. First, that entire structure of 8 8-byte entries the website is calling the "Global Descriptor Table", yet inside it, it clearly states that there is a pointer to the GDT (Global Descriptor Table). So does that mean it is pointing to itself? Or does that mean that the author of that article misnamed the overall structure?
Secondly, isn't the "GDT descriptor" a 6-byte structure (2 bytes for GDT size-1, and 4 bytes for the absolute address of the first byte of the GDT), rather than an 8-byte structure? Same thing for the IDT descriptor. Yet these descriptors seem to exist as 8-byte (not 6-byte) structures within this overall table of structures. What's going on here?
Thirdly, what is a "DS descriptor"? I've never heard of that before.

It seems there may be some inaccuracies in that document. So can somebody here clarify what is actually in the structure needed to switch to protected mode via the BIOS?

Reply 16 of 20, by jmarsh

User metadata
Rank Member
Rank
Member

It's pretty simple if you think about it. The GDT descriptor and IDT descriptor contain the limit (2 bytes) and address (3 bytes) to be loaded via LGDT/LIDT. The other bytes of the descriptor for those entries is ignored.
Without these the bios would have no way of knowing what limits or physical memory addresses to use for loading the GDT and IDT.
The DS/ES/SS/CS descriptors are all loaded into their respective segment registers.

Reply 17 of 20, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

your talking about two different things, a pointer to the GDT, and a GDT entry itself. Pointer to GDT is 6 bytes. GDT entry is 8 bytes. You will oftsen see people put the linear GDT pointer into the null descriptor.

honestly, you should really just use trans pmode or dos32/a or watcom c if this stuff is already confusing you.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: mega-tokyo.com ]-/\--

Reply 18 of 20, by videogamer555

User metadata
Rank Member
Rank
Member
jmarsh wrote on 2020-01-20, 05:47:

It's pretty simple if you think about it. The GDT descriptor and IDT descriptor contain the limit (2 bytes) and address (3 bytes) to be loaded via LGDT/LIDT. The other bytes of the descriptor for those entries is ignored.
Without these the bios would have no way of knowing what limits or physical memory addresses to use for loading the GDT and IDT.
The DS/ES/SS/CS descriptors are all loaded into their respective segment registers.

What is a DS descriptor?
I know what a "GDT descriptor" is. It is a limit and offset that describes the GDT. A "GDT descriptor" (aka "GDT pointer") tells the CPU how to find the GDT. Within the GDT there are a set of entries known as "GDT entries".
So the real question is what is a "DS descriptor"? I've never heard of such a thing. As far as I know, the GDT itself (via its GDT entries) contains pointers to code and data segments, so why does this special BIOS descriptor table need separate DS/ES/SS/CS descriptors, and what format are these 4 descriptors in. Do they look more like "GDT entries" (with all the info such entries provide) or do they look more like the "GDT descriptor" (a simple limit and address)?