VOGONS


First post, by Exploit

User metadata
Rank Member
Rank
Member

I'm curious about commercial real mode software that specifically expects the A20 gate to be disabled (with address wraparound at the 1 MB boundary) to function correctly and actively uses this wraparound.

Unfortunately, I haven't found such a list in the forum yet, but maybe we could put one together right here.

Do you know of any commercial real mode programs or games that break when the A20 gate is enabled (due to unexpected memory access above 1 MB)?

EDIT:
To track down such programs, you could modify an emulator to log A20 state changes and maybe even detect wraparounds. Then you'd just run the programs in that emulator. If you could communicate between the emulator and host over an emulated serial interface, you could use a batch file to report which program was started.

Reply 1 of 7, by Zup

User metadata
Rank Oldbie
Rank
Oldbie

I guess no such games should exist.

I mean, in a standard PC/XT (=640Kb or less) the wraparound exists between a reserved memory zone (high) and interrupt vectors and DOS (low). There is no good reason for a game to work there (except setting some interrupt vectors), and even less reason to jump between both zones.

In computers with EMS, that "high" zone may be used for EMS but still no reason to jump between EMS and DOS. 386 or better computers can use it to put some DOS thigs (DOSHIGH, LH)... still no reason to work there.

I have traveled across the universe and through the years to find Her.
Sometimes going all the way is just a start...

I'm selling some stuff!

Reply 2 of 7, by myne

User metadata
Rank l33t
Rank
l33t
Exploit wrote on 2026-01-16, 00:17:
I'm curious about commercial real mode software that specifically expects the A20 gate to be disabled (with address wraparound a […]
Show full quote

I'm curious about commercial real mode software that specifically expects the A20 gate to be disabled (with address wraparound at the 1 MB boundary) to function correctly and actively uses this wraparound.

Unfortunately, I haven't found such a list in the forum yet, but maybe we could put one together right here.

Do you know of any commercial real mode programs or games that break when the A20 gate is enabled (due to unexpected memory access above 1 MB)?

EDIT:
To track down such programs, you could modify an emulator to log A20 state changes and maybe even detect wraparounds. Then you'd just run the programs in that emulator. If you could communicate between the emulator and host over an emulated serial interface, you could use a batch file to report which program was started.

Wouldn't that overwrite important things eventually? Like the vga bios?

I built:
Convert old ASUS ASC boardviews to KICAD PCB!
Re: A comprehensive guide to install and play MechWarrior 2 on new versions on Windows.
Dos+Windows 3.11+tcp+vbe_svga auto-install iso template
Script to backup Win9x\ME drivers from a working install
Re: The thing no one asked for: KICAD 440bx reference schematic

Reply 3 of 7, by Jo22

User metadata
Rank l33t++
Rank
l33t++

"spell checker in the DOS-based versions of MS Word 2.x and 3.x. These versions were sold roughly from 1985 to 1987."
https://www.os2museum.com/wp/a-word-on-the-call-5-spell/

Microsoft/IBM Pascal and EXEPACK did depend on wrap-around, too, it seems.
https://www.os2museum.com/wp/the-a20-gate-it-wasnt-wordstar/

"Time, it seems, doesn't flow. For some it's fast, for some it's slow.
In what to one race is no time at all, another race can rise and fall..." - The Minstrel

//My video channel//

Reply 4 of 7, by jakethompson1

User metadata
Rank l33t
Rank
l33t

Those os2museum posts that Jo22 linked explain how it arises. Here is a higher level explanation.

Remember in C, memcpy() is undefined if the source and destination buffers overlap, while memmove() checks and copies in the correct direction when they overlap: if source > destination, copy forward; if source < destination, copy backward.
In the "backward" case, the author does not want to special-case the offset portion of the memory address crossing below zero, so they re-normalize the source and destination far pointers such that they are ds:fffx and es:fffx. To increase the offset by X bytes, the segment has to be decreased by X/16 bytes. If the buffers are in the first 64K-16 bytes of memory, this could cause the segment portion to cross below zero, but it still points to the same place so long as A20 wraparound is in place. Loadfix (HELP LOADFIX on DOS 6.x) works by simply taking up the first 64K of memory so that this crossover cannot happen. Also those posts explain, DOS=HIGH makes it more likely for this to happen in the first place, by making it more likely that the first 64K is free and not taken up by DOS, device drivers, and Command.

So to help answer the original question, the issue is that this wraparound could be hidden away in library code, even if the game author didn't intentionally rely on wraparound in their own code.

Reply 5 of 7, by mkarcher

User metadata
Rank l33t
Rank
l33t

Generally, you should be aware that the key point of the integer number representation used by all modern computers is that the adding and subtracting numbers does not care at all about whether the number is interpreted as signed or unsigned number. Looking at 16 bit numbers, we know that if you add 1 to 65535, you would get 65536, but that doesn't fit into 16 bits, so you get 0 instead. This means 65535 is "the number you need to add 1 to to get 0 as result", which is also the definition of negative 1. So if we treat a 16-bit number as signed we interpret the bit pattern that is associtated with the unsigned number 65535 as "-1". Essentially, in 16-bit arithmetic, 65535 and -1 are the same thing. So if you are using segment FFFF (65535), there is no distinction whether you intended to treat it as segment 65535 (which has just 16 bytes at the end of the address space, until it overflows), or you intended to treat it as segment -1 (in which the first 16 bytes are "before" the valid address space, but bytes 16 to 65535 do exist). If you do not mask A20 on 286 system, the computer forces the interpretation of "segment 65535" on you and prevents you to use the interpretation "segment -1", while both were equally valid on the 8086.

Reply 6 of 7, by jakethompson1

User metadata
Rank l33t
Rank
l33t
mkarcher wrote on 2026-01-16, 20:28:

Generally, you should be aware that the key point of the integer number representation used by all modern computers is that the adding and subtracting numbers does not care at all about whether the number is interpreted as signed or unsigned number. Looking at 16 bit numbers, we know that if you add 1 to 65535, you would get 65536, but that doesn't fit into 16 bits, so you get 0 instead. This means 65535 is "the number you need to add 1 to to get 0 as result", which is also the definition of negative 1. So if we treat a 16-bit number as signed we interpret the bit pattern that is associtated with the unsigned number 65535 as "-1". Essentially, in 16-bit arithmetic, 65535 and -1 are the same thing. So if you are using segment FFFF (65535), there is no distinction whether you intended to treat it as segment 65535 (which has just 16 bytes at the end of the address space, until it overflows), or you intended to treat it as segment -1 (in which the first 16 bytes are "before" the valid address space, but bytes 16 to 65535 do exist). If you do not mask A20 on 286 system, the computer forces the interpretation of "segment 65535" on you and prevents you to use the interpretation "segment -1", while both were equally valid on the 8086.

I wonder how close Intel came to suppressing A20 on the 80286 while in real mode, for 8086 compatibility. But that would break unreal mode, including the reset vector being at FFFFF0, and in 1980 or whenever this decision was being made, there wouldn't have been a base of 8086 commercial software depending on the wraparound. Do you think they did not even consider it, or like the behavior of push sp, it was just yet another item on the list of implementation differences?

Reply 7 of 7, by mkarcher

User metadata
Rank l33t
Rank
l33t
jakethompson1 wrote on 2026-01-16, 21:13:

I wonder how close Intel came to suppressing A20 on the 80286 while in real mode, for 8086 compatibility. But that would break unreal mode, including the reset vector being at FFFFF0, and in 1980 or whenever this decision was being made, there wouldn't have been a base of 8086 commercial software depending on the wraparound. Do you think they did not even consider it, or like the behavior of push sp, it was just yet another item on the list of implementation differences?

The stuff I know as "unreal mode" is "real mode" with a segment limit of 4G, with obviously doesn't exist on the 80286. This kind of "unreal mode" got born with the 80386, which allows you to use 32-bit addressing schemes in real mode. Were you thinking about the LOADALL trick used by MS-DOS HIMEM when you wrote "unrel mode"?

There would be a quite obvious way to not break the reset vector, and yet get 8086 compatiblity: Instead of masking A20, you could block the carry from bit 19 to bit 20 in the adder that adds the offset to the base address from the descriptor cache. With the carry blocked, you would get 16 individually wrapping 1M address spaces, and with the carry unblocked, you get a single 16M address space.

My guess is that Intel didn't consider the use case of a system that is both (a) requires compatibility to an 8086 system and (b) makes use of more than 1MB address space at the same time. If you just want to use the 80286 as "faster 8086" (which it clearly is due to the faster bus access), you can just ignore A20..A23 on the mainboard all the time and run your standard 8086/8088 software, even if it happens to use the address wraparound. On the other hand, if you design a modern system with possibly more than 1MB of address space, you would just enter protected mode anyway and there would be no need for 8086 compatibilty. Both the use case of a legacy system that ignores A20 (and A21..A23) and the use case of a modern system with a protected mode OS do not require a 1MB wraparound implemented inside the 80286 processor.