While trying to use a "modern" sound card (an Aztech Sound Galaxy Pro 16 II) in an XT compatible 8086 computer, I encountered the problem that the drivers and tools (like the mixer initialization tool and the resource configuration tool) are compiled with 286 real mode instructions (ENTER
, LEAVE
, PUSH imm8
, PUSH imm16
, SHL r/m, imm8
). I considered different approaches:
- Disassemble the whole program with IDA, mark up all offsets, and reassemble it with an assembler that synthesizes 8086 instructions to emulate the 80286 instructions.
- Re-Engineer the tools I need
- Write an automatic debugger, that places breakpoints on all 80286 instructions and emulates them.
I dropped the first two ideas because of the great amount of manual work they need after getting the idea for the third approach. I am in no way striving for perfect 286 emulation, just emulation of the features typically used by compiled C programs. I am sure some one had that idea before me, though. Does anyone know of an implementation of that idea, so I don't have to implement it myself?
I am aware that I don't have to use that specific sound card, but I anticipate I will repeatedly encounter software that uses 286 instructions without being otherwise useless on XT computers, so a generic solution might be helpful in the future.
The program at hand, HWSET.EXE
, contains the following 286 real mode instructions (and a consideration, how easy the JMP FAR
suggestion by Raffzahn could be implemented). This list is complete according to the list of unsupported first bytes of the 8086. I made no effort to detect instructions that are invalid on an 8086 only due to certain bits in subsequent bytes, as I am not aware of any:
- 27 instances of
ENTER
, 22 of them asENTER 2, 0
. Enter is 4 Bytes, so aJMP FAR
overwrites the first byte of the following instruction, which isPUSH SI
,PUSH DI
,MOV AX, imm16
orPUSH imm8
- 61 insances of
LEAVE; RET
(this is more thanENTER
because of functions with multiple return instructions). This is just 2 bytes, and the bytes after these two bytes can not be patched, asRET
is followed by a new entry point. - 33 instances of
PUSH imm16
- 145 instances of
PUSH imm8
(most of themPUSH 0
orPUSH 1
(these push instructions are generally used in conjunction withCALL (near)
, so there are 5 bytes at least in total. - 18 instances of
SHL r8, imm8
(with imm8 != 1), no obvious usage pattern, but 2 bytes afterwards seem to be at all samples I inspected by hand. - 25 instances of
SHR r8, imm8
(with imm8 != 1), seems to be from macro-assisted assembly code. This 3-byte instruction is mostly followed by 2 pops, so it can be replaced by a far jump. - 6 instances of imul r16, rm16, imm8