Page 1 of 2

v86 mode

Posted: Mon Dec 20, 2021 10:39 am
by YDeeps1
I'm attempting to implement and make use of V86 mode to use the bios for easy switching of graphics and resolutions.
I have a couple of questions which I couldn't find an answer to and so I am hoping to get some help setting it up and questions answered here.

Firstly, are you able to run code and have a stack above 1MB in V86 mode? Since 16-bit systems can only access data at around 64KB (going up to 1MB? also confused about that) I'm wondering if I need to map the V86 code to reside in lower segments of memory to be able to actually access them.

Re: v86 mode

Posted: Mon Dec 20, 2021 4:31 pm
by Gigasoft
In Virtual 8086 mode, all segments have their base address calculated like in real mode, by shifting the selector left by 4 bits, and their limit is fixed at 0xffff. Therefore, the maximum addressable linear address is 0x10ffef, and all code and data must be mapped at a low address.

Re: v86 mode

Posted: Mon Dec 20, 2021 8:10 pm
by Octocontrabass
YDeeps1 wrote:I'm attempting to implement and make use of V86 mode to use the bios for easy switching of graphics and resolutions.
Modern PCs have UEFI and GOP, so v86 mode won't help you there.

Slightly older PCs have a BIOS that assumes you'll run a 64-bit version of Windows, and 64-bit Windows never uses v86 mode, so the BIOS code may not run correctly in v86 mode.

Have your bootloader set the graphics mode instead. How often do you expect users of your OS to change the resolution, anyway?

Re: v86 mode

Posted: Tue Dec 21, 2021 11:56 am
by YDeeps1
Octocontrabass wrote:
YDeeps1 wrote:I'm attempting to implement and make use of V86 mode to use the bios for easy switching of graphics and resolutions.
Modern PCs have UEFI and GOP, so v86 mode won't help you there.

Slightly older PCs have a BIOS that assumes you'll run a 64-bit version of Windows, and 64-bit Windows never uses v86 mode, so the BIOS code may not run correctly in v86 mode.

Have your bootloader set the graphics mode instead. How often do you expect users of your OS to change the resolution, anyway?
Sounds strange but I want to switch to and from text mode and graphics mode as per my design for now instead of implementing fonts and position tracking (for now).

I did have some luck doing so via interacting with the VGA hardware with IO ports following http://files.osdev.org/mirrors/geezer/o ... cs/modes.c .

I was able to setup switching to and from text mode however I was only able to get 320x200x256 (oddly enough I was only able to use 64 colours, after the 63rd colour it all just came out as black pixels) working; and to implement any decently looking and sized text/images I'd need a higher resolution with at least 256 colours.

I was trying to use the BIOS in hopes of achieving a better resolution and better colour range.

If all else fails I will probably get the BIOS to set the resolution and colour depth for me and proceed by implementing my own fonts to mimic the VGA text mode.

I also realised I fell into the trap of the XY problem.

Re: v86 mode

Posted: Tue Dec 21, 2021 11:56 am
by YDeeps1
Gigasoft wrote:In Virtual 8086 mode, all segments have their base address calculated like in real mode, by shifting the selector left by 4 bits, and their limit is fixed at 0xffff. Therefore, the maximum addressable linear address is 0x10ffef, and all code and data must be mapped at a low address.
I feared so, thank you.

Re: v86 mode

Posted: Tue Dec 21, 2021 8:37 pm
by Octocontrabass
YDeeps1 wrote:Sounds strange but I want to switch to and from text mode and graphics mode as per my design for now instead of implementing fonts and position tracking (for now).
You may be overestimating the difficulty of setting up a simple bitmap font.
YDeeps1 wrote:I did have some luck doing so via interacting with the VGA hardware
Modern PCs don't have VGA hardware. VGA is limited to about 320x240 with 256 colors, or 800x600 with 16 colors.
YDeeps1 wrote:(oddly enough I was only able to use 64 colours, after the 63rd colour it all just came out as black pixels)
The example code you followed skipped a step: you need to program the DAC. Those 64 colors you saw are the ones the BIOS programs into the DAC whenever it sets up an EGA-compatible mode.

Re: v86 mode

Posted: Wed Dec 22, 2021 5:04 am
by mid
I don't see him mentioning designing for "modern" PCs anywhere.

Re: v86 mode

Posted: Wed Dec 22, 2021 5:21 am
by iansjack
mid wrote:I don't see him mentioning designing for "modern" PCs anywhere.
That's actually a good point, as modern PCs may not have a BIOS either. But it's as well to be aware of trends in computer design which would render development of an OS depending upon the BIOS and/or VGA obsolete.

The whole point is rather moot as the direction in OS design is now towards 64-bit code, which obviates the use of v86 mode. The v86 approach has always seemed rather dubious to me as it's more complicated, and error prone, than simply using a graphics mode from the start.

Re: v86 mode

Posted: Wed Dec 22, 2021 6:55 am
by YDeeps1
iansjack wrote:
mid wrote:I don't see him mentioning designing for "modern" PCs anywhere.
That's actually a good point, as modern PCs may not have a BIOS either. But it's as well to be aware of trends in computer design which would render development of an OS depending upon the BIOS and/or VGA obsolete.

The whole point is rather moot as the direction in OS design is now towards 64-bit code, which obviates the use of v86 mode. The v86 approach has always seemed rather dubious to me as it's more complicated, and error prone, than simply using a graphics mode from the start.
All UEFI motherboards I've come across, even modern ones include a "legacy boot" option which emulates BIOS unless they've started to get rid of them? Since my OS uses text mode (for now) and text mode is only supported on BIOS, it must be emulating the BIOS (unless grub is doing some dark magic).

Re: v86 mode

Posted: Wed Dec 22, 2021 9:36 am
by rdos
YDeeps1 wrote: All UEFI motherboards I've come across, even modern ones include a "legacy boot" option which emulates BIOS unless they've started to get rid of them? Since my OS uses text mode (for now) and text mode is only supported on BIOS, it must be emulating the BIOS (unless grub is doing some dark magic).
Same here, although I've not tested with motherboards the last year or so.

Still, the BIOS mode setting on Intel is broken both on UEFI and BIOS and doesn't support wide-screen modes (or any other non-standard mode). Though, this problem can be avoided by buying AMD systems.

I have V86 mode setting code that works "on-the-fly", but I probably wouldn't design it that way given that newer computers might not boot with BIOS. Rather, I typically let the boot-process set a mode even with BIOS, and this makes the code simpler since UEFI & BIOS work the same way.

Re: v86 mode

Posted: Thu Dec 23, 2021 9:03 am
by YDeeps1
Right so I chose to go the GRUB and own font route.

I chose mode 0 (linear pixel mode) and then chose 640x480x24 for the graphical mode.

All appears to work fine however when filling pixels until 640*35, no more pixels are outputted at around the point shown on the image.
https://imgur.com/a/TUdal6B

I made this simple quick script to test the colour depth which should fill the entire screen white but it does not and stops prematurely.

Code: Select all

for (uint32_t i = 0; i < 640 * 480; i++) {
    uint8_t* location = (uint8_t*)0xA0000 + (i * 3);
        
    // R-G-B
    *(location+2) = 255;
    *(location+1) = 255;
    *(location+0) = 255;
}
I tested different colours and emulators with the same result occurring. Anything vital I missed here?

Re: v86 mode

Posted: Thu Dec 23, 2021 4:05 pm
by kzinti
You can only access 64 KB of memory at 0xA0000. This corresponds to 34 rows of pixels at a width of 640 pixels and 3 bytes/pixel. I think this is what you might have run into.

Instead of accessing memory at 0xA0000, you should use VBE to setup the desired resolution. VBE will map all the video memory to some address that you can then use instead of 0xA0000.

Re: v86 mode

Posted: Thu Dec 23, 2021 4:19 pm
by YDeeps1
kzinti wrote:You can only access 64 KB of memory at 0xA0000. This corresponds to 34 rows of pixels at a width of 640 pixels and 3 bytes/pixel. I think this is what you might have run into.

Instead of accessing memory at 0xA0000, you should use VBE to setup the desired resolution. VBE will map all the video memory to some address that you can then use instead of 0xA0000.
Why am I only able to access 64KB of memory at that address? I thought PMode came with no strings attached.
And am I able to make this adjustment without calls to the BIOS? I am held back by quite a lot of restrictions surrounding real/virtual 16-bit mode hence why I am unable to use the BIOS/UEFI.

Re: v86 mode

Posted: Thu Dec 23, 2021 4:32 pm
by kzinti
There is a windows of 128KB at 0xA0000 for video memory. The video BIOS is at 0xC0000. See the PC memory map at https://wiki.osdev.org/Memory_Map_(x86).

Typically video cards will map chunks of 64 KB at 0xA0000 and 0xB0000. They normally provide a way to map different parts of their video memory to 0xA0000 and/or 0xB0000. This is known as bank-switching. How this is achieved (and whether or not it is even possible) is video-card specific. There is no standard way.

This is where VESA/VBE comes in: it provides an interface to set the video mode, but also to achieve bank-switching on any video card. The way this works is the video card vendor implements the VBE calls in the video BIOS.

If you are unable to use the video card's VBE implementation, your can scan the PCI bus to try and find if the video card framebuffer was mapped somewhere else, but this is guess work. The usual alternative would be to figure out which video card / chipset you have and find the documentation for it (typically a list of registers and what they do). This is basically just like writing a video driver.

Re: v86 mode

Posted: Thu Dec 23, 2021 4:47 pm
by YDeeps1
kzinti wrote:There is a windows of 128KB at 0xA0000 for video memory. The video BIOS is at 0xC0000. See the PC memory map at https://wiki.osdev.org/Memory_Map_(x86).

Typically video cards will map chunks of 64 KB at 0xA0000 and 0xB0000. They normally provide a way to map different parts of their video memory to 0xA0000 and/or 0xB0000. This is known as bank-switching. How this is achieved (and whether or not it is even possible) is video-card specific. There is no standard way.

This is where VESA/VBE comes in: it provides an interface to set the video mode, but also to achieve bank-switching on any video card. The way this works is the video card vendor implements the VBE calls in the video BIOS.

If you are unable to use the video card's VBE implementation, your can scan the PCI bus to try and find if the video card framebuffer was mapped somewhere else, but this is guess work. The usual alternative would be to figure out which video card / chipset you have and find the documentation for it (typically a list of registers and what they do). This is basically just like writing a video driver.
Mind showing me a way I can find low-level manufacturer documentation for things like this? I don't really see much documentation for them (I am using an Nvidia GPU to start off with).

And does GRUB not provide this kind of information?