VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've noticed that, when enabling the "Quit on #UD(undefined) instruction" and running various software on my 80286 core, I get #UD exceptions(actual 80286 opcodes that are officially(and unofficially too afaik, like the GRP5 /7 opcode) invalid). This seems to be because it's executing code in bogus memory. Anyone knows a way to find the offending instruction? Is there a way to find out where my 80286 emulation screws up(even my 80186('NEC V30') emulation on XT with ET4000 BIOS crashes because of an #UD opcode)? (#UD opcodes on both 80(1)86 and 80286 are currently implemented to terminate the emulator for testing)

Just tried running Prince of Persia for MS-DOS on my 80286 core. It terminates because of an #UD.

Edit: Just tried installing Windows 3.0. It crashes trying to copy the SETUP.EXE to the first hard disk (second HDD is mounted read-only).

Edit: Just gotten a #UD after an ADD instruction(opcode 00h) during POST? Something seems to go wrong here? The current(invalid) opcode is 0xFF(GRP5 opcode), while the previous opcode was:
- 00(ADD) at a strange address.

8086+ opcodes: https://bitbucket.org/superfury/unipcemu/src/ … 086.c?at=master
80186+ opcodes: https://bitbucket.org/superfury/unipcemu/src/ … V30.c?at=master
80286+ opcodes: https://bitbucket.org/superfury/unipcemu/src/ … 286.c?at=master
CPU core combining all of them: https://bitbucket.org/superfury/unipcemu/src/ … cpu.c?at=master
CPU protected mode timings and real mode instruction parameters information(modr/m, immediate parameters etc): https://bitbucket.org/superfury/unipcemu/src/ … ngs.c?at=master

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 6, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

Edit: Just gotten a #UD after an ADD instruction(opcode 00h) during POST? Something seems to go wrong here? The current(invalid) opcode is 0xFF(GRP5 opcode), while the previous opcode was:
- 00(ADD) at a strange address.

Executing 00 ADD before stuff goes wrong is usually a sign that something is going bad (you are executing form uninitialized memory). What I did in my emulator is increment a counter every time I hit the 00 opcode (and reset if not 00) and if I hit it 5 times in a row I would assert (and break in the debugger) because that usually meant I was out in the bushes. If you do not catch it right then it will continue executing and eventually hit what looks like valid opcodes again sending you on a wild goose chase.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 2 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've implemented the logging of bogus memory (triggered by 5 ADD '0000h' instructions in currently executing memory(non-prefetched) at CS:(E)IP). Trying to run the SETTUP.COM from the AT Diagnotics Disk from MS-DOS 5.0a only logs the following information(I'm using revision 3 of the AT BIOS):

Unknown opcode detected: 63@1828:000020B0, Previous opcode: CF@F000:00000000

So something's pointing to a handler containing an IRET instruction at the start of the BIOS ROM? Looking at the BIOS ROM itself(which is a ROM located at FF0000) doesn't reveal this byte? So is this byte copied into low RAM and overwritten by software?

Strangely, looking at the mapping of the BIOS ROM, it's mapped to both the high (FFFF0000 and FF0000) and low (F0000) memory areas. So that IRET at that position, which is reported, isn't supposed to exist!

Looking at the current ROM loaded, (u27&47), it reveals F000:0000 should contain (u27=Even, u47=Odd memory addresses) opcode 36h. So either it's in protected mode, executing an invalid loaded CS, which isn't at segment F000) or it's using LOADALL to load a segment descriptor with a starting address that doesn't match?)

Could it be that some kind of exception or something like that isn't clearing the prefetch queue properly?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've just tried running Day of the Tentacle on my 80286 AT emulation. It eventually tries to handle a #GP, which points to a certain address.
I see the prefetch being buffered with the following information directly following the interrupt Dh(#GP handler):

2e CS:
6f OUTSW [SI]

Since SI contains 0xFFFF, it will result in a #GP fault, which jumps back to the opcode infinitely.
The interrupt vector points to 0020:1BD0.

It executes a OUTSW instruction:
OUTSW CS:FFFF

Since CS is 20 and FFFF+1 is past the segment limit on the 80286, it crashes the application in an infinite exception handler trigger loop.

Filename
UniPCemu CPU interrupt calls running DOTT.zip
File size
3.11 MiB
Downloads
29 downloads
File comment
A log of all interrupt calls up to and including the infinite exception loop.
File license
Fair use/fair dealing exception

The log entries are structured as follows:
[EXECTIME] Interrupt [INTNR]=[INTSEG]:[INTOFFS]@[CAUSESEG]:[CAUSEOFFS]([CAUSEOPCODE])

Anyone can see what's causing this? It seems to have something to do with exceptions, but which one is the cause?

Strangely enough, during booting, I notice that the IDT is loaded with a base of F4759, later cleared (probably through a CPU reset) to 0000(limit 3FF). This is probably done by the Sound Blaster 2.0 driver(or the XT-IDE BIOS)?

Looking at the exceptions raised in real mode again, I see a LODSW being executed at 0000:40EE, which takes offset FFFF as it's base(previous opcode was B2h)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 6, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

I find it odd that DOS interrupt vector points to segment 21h because that is in the middle of interrupt vectors, but on the other hand it's pretty clever to have it on segment 21h and offset is high enough to point to actual code.

What the DX value is during the offending OUTSW [CS:SI]?

But it does not really matter, as take a look at this:

00:05:23:10.07744: Interrupt 21=0000:000040EB@2A4E:3A8E(CD)

As I read it, when code at 2A4E:3A8E executes CD 21 (INT 21H), it jumps to vector 0000:40EB, but previously when somebody called INT 21H, the vector was 0021:40EB. So this ends up executing garbage already. So at 0000:40EE where the AD opcode (LODSW) causes the exception to trigger so it goes to execute the exception code at 0020:1BD0, and there is the 6F opcode (OUTSW) which keeps triggering the exception.

Something has changed the int 21h segment, or something does not read the segment properly. Find out why it gets 0000h instead of 0021h and you'll solve the issue.

Note that INT 0Dh is also vector for IRQ5. Is your Sound Blaster IRQ set to 5? Then it is not an exception but real IRQ 5 from SB.

Reply 5 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK, so there's a problem with the segment address of interrupt 21h.
Yes, the Sound Blaster uses IRQ5, which I've set up in DOTT using Dosbox, since the settings menu crashes when saving the settings in UniPCemu.

Before many of the fixes(mostly exception handlers blocking writes to and loads from memory, which is now checked before writing registers&memory(instead of aborting in the middle of an (stack/multiple memory/register changing) operation))), sound(sounded like white noise) was played back by DOTT through the Sound Blaster 2.0. Now it's simply quietly hanging(no samples being output). So although protection works better now, it still does something extremely wrong somewhere(loop going too far, seeing as SI=FFFF during a OUTSW, which shouldn't happen anyway on a 80286(illegal word address in memory on 286+).

I'll look if I can find the offending instruction writing to the word at address (84h/)85h.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've just found a little bug in the checking of segment limits (It's Expand-Down/Up code to be exact). It was checking for bit 2 in the Access Rights byte to be cleared in order to check for Expand-Down segments(Which checks the same bit to be set). I've fixed this to first check bit 3 (bit value of 8 ), then check the usual E bit(bit 2) to be set in order to implement Expand-Down segment limits. This might have been the cause of the crashes in Real Mode(Causing the Stack to be invalid)? Since the Stack Segment is usuallly loaded with bits 2&3 set to 0 and 0(Data segment, Expand-Up), that caused the check to be fully ignored. But when setting it to Data Segment, Expand up(as is the case of an Expand-Up Stack), it would result in the check to be ignored(as well as Granularity in 32-bit protected mode), and the check to check like an Expand-Up segment. Also Conforming Code segments would skip the entire check(which wouldn't be a problem, as it's a Conforming Bit instead. Although the first check might be executed (bit 4=0), the second check (E bit being 1) would fail because it cannot be 0 and 1 at the same time, thus skipping the check).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io