Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
ecm

Homepage E-mail

Düsseldorf, Germany,
28.10.2025, 17:20
 

ROM-BIOS leaves ds and es limits beyond 64 KiB (Developers)

I just noticed that testing instructions like mov ax, [FFFF] and mov ax, [es:FFFF] do not cause a fault when I boot the physical Pentium 3 (686) machine into bootable lDebug. (You want to install intfaults before running such tests, to have the debugger catch these Real 86 Mode faults in case they do occur.) With cs, ss, or fs overrides the instruction does fault (int 0Ch for ss, int 0Dh else).

If I boot using boot protocol msdos7 hda2 followed by q, which runs a Himem driver, then regardless of the involved segment the instruction does fault. (This is without an EMM that switches to Virtual 86 Mode, the machine is still in Real 86 Mode.)

So I assume that the ROM-BIOS leaves ds and es limits in an "unreal mode" state of higher segment limits than the 64 KiB expected for Real 86 Mode. Did you know that this is done by some systems?

---
l

Oso2k

28.10.2025, 21:46

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> I just noticed that testing instructions like mov ax, [FFFF]
> and mov ax, [es:FFFF] do not cause a fault when I boot the
> physical Pentium 3 (686) machine into bootable lDebug. (You want to
> install intfaults before running such tests, to have the
> debugger catch these Real 86 Mode faults in case they do occur.) With cs,
> ss, or fs overrides the instruction does fault (int 0Ch for ss, int 0Dh
> else).
>
> If I boot using boot protocol msdos7 hda2 followed by
> q, which runs a Himem driver, then regardless of the involved
> segment the instruction does fault. (This is without an EMM that switches
> to Virtual 86 Mode, the machine is still in Real 86 Mode.)
>
> So I assume that the ROM-BIOS leaves ds and es limits in an "unreal mode"
> state of higher segment limits than the 64 KiB expected for Real 86 Mode.
> Did you know that this is done by some systems?

Yes. You'd need to verify values of CR0, GDT and IDT but it is possible that some BIOSes, games and other software can/will leave the host in Unreal Mode accidentally.

One fun trick is to write to VGA buffer space using a single 32-bit instruction while in Unreal Mode.

mov ebx,A0000
mov [ds:ebx], byte 1 ; set the pixel "white" using default color palette



https://en.m.wikipedia.org/wiki/Unreal_mode#Uses

https://wiki.osdev.org/Unreal_Mode

ecm

Homepage E-mail

Düsseldorf, Germany,
28.10.2025, 22:03

@ Oso2k
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> One fun trick is to write to VGA buffer space using a single 32-bit
> instruction while in Unreal Mode.
>
> mov ebx,A0000
> mov [ds:ebx], byte 1 ; set the pixel "white" using default color palette
>


I can read from the word at segment 0 offset B8000 to read the text mode buffer. I just checked again, ds and es have higher limits, cs, ss, fs, and also gs do not. Also, the ROM-BIOS identifies itself as "Award Medallion BIOS v6.0", "Copyright (C) 1984-2000", running an "ASUS MED 2001 ACPI BIOS Revision 1009". At the bottom of the startup screen it reads "06/12/2001-VT694X-MED 2001".

---
l

tkchia

Homepage

06.11.2025, 17:29

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

Hello ecm,

> I can read from the word at segment 0 offset B8000 to read the text mode
> buffer. I just checked again, ds and es have higher limits, cs, ss, fs, and
> also gs do not. Also, the ROM-BIOS identifies itself as "Award Medallion
> BIOS v6.0", "Copyright (C) 1984-2000", running an "ASUS MED 2001 ACPI BIOS
> Revision 1009". At the bottom of the startup screen it reads
> "06/12/2001-VT694X-MED 2001".

Interesting finding!

Since this is real mode, I suppose another thing to try is to use the 0x40:0x67 + CMOS 0x0f trick (as outlined in RBIL) to reset the CPU segment registers to something like their power-on state, and see what happens from there...

(I recall it might be necessary to enable A20 for that, by the way.)

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

ecm

Homepage E-mail

Düsseldorf, Germany,
06.11.2025, 20:13

@ tkchia
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> Interesting finding!
>
> Since this is real mode, I suppose another thing to try is to use the
> 0x40:0x67 + CMOS 0x0f trick (as outlined in RBIL)
> to reset the CPU segment registers to something like their power-on state,
> and see what happens from there...
>
> (I recall it might be necessary to enable A20 for that, by the way.)

I'm not finding anything on the web version of the list at fd.lod.bz/rbil, could you provide a link to that part?

---
l

ecm

Homepage E-mail

Düsseldorf, Germany,
06.11.2025, 20:23

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> > Interesting finding!
> >
> > Since this is real mode, I suppose another thing to try is to use the
> > 0x40:0x67 + CMOS 0x0f trick (as outlined in
> RBIL)
> > to reset the CPU segment registers to something like their power-on
> state,
> > and see what happens from there...
> >
> > (I recall it might be necessary to enable A20 for that, by the way.)
>
> I'm not finding anything on the web version of the list at fd.lod.bz/rbil,
> could you provide a link to that part?

This? https://fd.lod.bz/rbil/cmos/other/r0f.html

---
l

tkchia

Homepage

06.11.2025, 23:07

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

Hello ecm,

> This? https://fd.lod.bz/rbil/cmos/other/r0f.html

Yes, this is it! :-) And https://fd.lod.bz/rbil/memory/other/m00400067.html .

Robert Collins has a more detailed discussion at https://www.rcollins.org/articles/pmbasics/tspec_a1_doc.html .

The 0x40:0x67 + CMOS 0x0f + CPU reset mechanism is the way to return from protected mode to real mode on a 286 PC. But it might possibly also work with your Pentium's BIOS. And I think you do not actually need to switch to protected mode to be able to use it.

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

bretjohn

Homepage E-mail

Rio Rancho, NM,
30.10.2025, 16:49

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> I just noticed that testing instructions like mov ax, [FFFF]
> and mov ax, [es:FFFF] do not cause a fault when I boot the
> physical Pentium 3 (686) machine into bootable lDebug. (You want to
> install intfaults before running such tests, to have the
> debugger catch these Real 86 Mode faults in case they do occur.) With cs,
> ss, or fs overrides the instruction does fault (int 0Ch for ss, int 0Dh
> else).
>
> If I boot using boot protocol msdos7 hda2 followed by
> q, which runs a Himem driver, then regardless of the involved
> segment the instruction does fault. (This is without an EMM that switches
> to Virtual 86 Mode, the machine is still in Real 86 Mode.)
>
> So I assume that the ROM-BIOS leaves ds and es limits in an "unreal mode"
> state of higher segment limits than the 64 KiB expected for Real 86 Mode.
> Did you know that this is done by some systems?

The way it works on the original 8086/8088 CPUs, which I think is what should be emulated by default, is obviously that it wouldn't generate a fault (the old CPU's didn't have segment faults). The issue is what byte ends up in AH when you do something like a MOV AX,[FFFFh]. Is it the byte at DS:[0000h] or the byte at the linear address one byte above DS:[FFFFh]. I believe it should be DS:[0000h], but am not 100% positive. I do know when you use high _segment_ numbers they roll over to zero so you can't access the HMA unless you enable A20 (which 8086/8088 CPU's didn't have, either).

ecm

Homepage E-mail

Düsseldorf, Germany,
30.10.2025, 18:49

@ bretjohn
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> The way it works on the original 8086/8088 CPUs, which I think is what
> should be emulated by default, is obviously that it wouldn't generate a
> fault (the old CPU's didn't have segment faults).

Yes, indeed. I previously discussed this on stackoverflow and on the dosemu2 site. As bartoldeman stated there:

> > it's documented in "Differences From 8086" in the original 80386 programmer's manual. e.g. https://pdos.csail.mit.edu/6.828/2018/readings/i386.pdf
>
> Page 211.

Quoting from there:

> Operand crossing offset 0 or 65,535.
>
> On the 8086, an attempt to access a memory operand that crosses
> offset 65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g.,
> PUSH a word when SP = 1) causes the offset to wrap around modulo
> 65,536. The 80386 raises an exception in these cases──exception 13 if
> the segment is a data segment (i.e., if CS, DS, ES, FS, or GS is being
> used to address the segment), exception 12 if the segment is a stack
> segment (i.e., if SS is being used).
>
> Sequential execution across offset 65,535.
>
> On the 8086, if sequential execution of instructions proceeds past
> offset 65,535, the processor fetches the next instruction byte from
> offset 0 of the same segment. On the 80386, the processor raises
> exception 13 in such a case.

For more information on the IP fault, refer to https://www.os2museum.com/wp/does-eip-wrap-around-in-16-bit-segments/ as well.

> The issue is what byte
> ends up in AH when you do something like a MOV AX,[FFFFh]. Is
> it the byte at DS:[0000h] or the byte at the linear address one byte above
> DS:[FFFFh]. I believe it should be DS:[0000h], but am not 100% positive.

Yes, on the NEC V20 (as used by my HP 95LX) it does actually access the byte at offset 0000h, not 10000h, as the high byte. Not sure what Intel's 8086, 186, and 286 did.

---
l

bretjohn

Homepage E-mail

Rio Rancho, NM,
31.10.2025, 01:45

@ ecm
 

ROM-BIOS leaves ds and es limits beyond 64 KiB

> Yes, on the NEC V20 (as used by my HP 95LX) it does actually access the
> byte at offset 0000h, not 10000h, as the high byte. Not sure what Intel's
> 8086, 186, and 286 did.

And that's something I wouldn't necessarily trust that any of the modern VM's get correct, either. The only way I would believe the test was correct is if I did it on a real CPU.

I know the LOADFIX program included with early versions of DOS was supposed to resolve memory rollover issues that would crash some programs, but I don't know the exact details.

ecm

Homepage E-mail

Düsseldorf, Germany,
06.11.2025, 20:20

@ bretjohn
 

LOADFIX

> I know the LOADFIX program included with early versions of DOS was supposed
> to resolve memory rollover issues that would crash some programs, but I
> don't know the exact details.

I think that LOADFIX just reserves memory in the first 64 KiB of the Low Memory Area before loading the application. This means that segmented pointer underflow doesn't happen, including when using naively anti-normalised far pointers. That is, so that applications like the original exepack stub won't underflow and access the HMA unwittingly. This is purely an A20-related problem.

I guess that MS-DOS v5 and up will disable A20 on exec, which helps exepack. Upon an int 21h A20 will be enabled to access the DOS. LOADFIX then helps if a program would depend on A20 wraparound after making any int 21h calls.

---
l

Back to index page
Thread view  Board view
22852 Postings in 2135 Threads, 402 registered users (0 online)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum