Cleaned up conditional jump handling
This commit is contained in:
parent
e057bd7a05
commit
2784934491
10 changed files with 135 additions and 50 deletions
|
|
@ -8,16 +8,16 @@
|
||||||
"ram": [
|
"ram": [
|
||||||
{ "id": "pc386.ramLow",
|
{ "id": "pc386.ramLow",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0x00000,
|
"addr": 0,
|
||||||
"size": 0xa0000,
|
"size": 655360,
|
||||||
"test": false
|
"test": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rom": [
|
"rom": [
|
||||||
{ "id": "pc386.romTests",
|
{ "id": "pc386.romTests",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0xf0000,
|
"addr": 983296,
|
||||||
"size": 0x10000,
|
"size": 65280,
|
||||||
"file": "/tests/pc/80386/tests.json",
|
"file": "/tests/pc/80386/tests.json",
|
||||||
"notify": ""
|
"notify": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,8 @@ A BackTrack index is encoded as a 32-bit value with three parts:
|
||||||
|
|
||||||
This represents a total of 31 bits, with bit 31 reserved.
|
This represents a total of 31 bits, with bit 31 reserved.
|
||||||
|
|
||||||
For example, look at one of the last things a ROM does during boot: load a disk sector into RAM. It will be up to the
|
For example, look at one of the last things a ROM does during boot: loading a disk sector into RAM. It will be up to the
|
||||||
disk controller (or DMA controller if one is used) to create a BackTrack object representing the sector that was read,
|
disk controller (or DMA controller, if used) to create a BackTrack object representing the sector that was read,
|
||||||
adding that object to the global BackTrack object array, and then associating the corresponding BackTrack index with
|
adding that object to the global BackTrack object array, and then associating the corresponding BackTrack index with
|
||||||
the first byte of RAM where the sector was loaded. Subsequent bytes of RAM containing the rest of the sector will refer
|
the first byte of RAM where the sector was loaded. Subsequent bytes of RAM containing the rest of the sector will refer
|
||||||
to the same BackTrack object, using BackTrack indexes containing offsets 1-511.
|
to the same BackTrack object, using BackTrack indexes containing offsets 1-511.
|
||||||
|
|
|
||||||
|
|
@ -1603,7 +1603,7 @@ if (DEBUGGER) {
|
||||||
/*
|
/*
|
||||||
* When we dump the EXT word, we mask off the LIMIT1619 and BASE2431 bits, because those have already
|
* When we dump the EXT word, we mask off the LIMIT1619 and BASE2431 bits, because those have already
|
||||||
* been incorporated into the limit and base properties of the segment register; all we care about here
|
* been incorporated into the limit and base properties of the segment register; all we care about here
|
||||||
* are whether EXT contains any of the AVAIL (0x10), BIG (0x40) or GRANULARITY (0x80) bits.
|
* are whether EXT contains any of the AVAIL (0x10), BIG (0x40) or LIMITPAGES (0x80) bits.
|
||||||
*/
|
*/
|
||||||
this.println(sDump + " dpl=" + str.toHexByte(seg.dpl) + " type=" + str.toHexByte(seg.type >> 8) + " (" + sType + ")" + " ext=" + str.toHexWord(seg.ext & ~(X86.DESC.EXT.LIMIT1619 | X86.DESC.EXT.BASE2431)));
|
this.println(sDump + " dpl=" + str.toHexByte(seg.dpl) + " type=" + str.toHexByte(seg.type >> 8) + " (" + sType + ")" + " ext=" + str.toHexWord(seg.ext & ~(X86.DESC.EXT.LIMIT1619 | X86.DESC.EXT.BASE2431)));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -103,10 +103,10 @@ var X86 = {
|
||||||
MASK: 0xfff8 // table index
|
MASK: 0xfff8 // table index
|
||||||
},
|
},
|
||||||
DESC: { // Descriptor Table Entry
|
DESC: { // Descriptor Table Entry
|
||||||
LIMIT: {
|
LIMIT: { // LIMIT bits 0-15
|
||||||
OFFSET: 0x0
|
OFFSET: 0x0
|
||||||
},
|
},
|
||||||
BASE: {
|
BASE: { // BASE bits 0-15
|
||||||
OFFSET: 0x2
|
OFFSET: 0x2
|
||||||
},
|
},
|
||||||
ACC: { // bit definitions for the access word (offset 0x4)
|
ACC: { // bit definitions for the access word (offset 0x4)
|
||||||
|
|
@ -166,7 +166,7 @@ var X86 = {
|
||||||
* is 0xffffffff instead of 0xffff.
|
* is 0xffffffff instead of 0xffff.
|
||||||
*/
|
*/
|
||||||
BIG: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
|
BIG: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
|
||||||
GRANULARITY: 0x0080, // clear if limit is bytes, set if limit is 4Kb pages
|
LIMITPAGES: 0x0080, // clear if limit granularity is bytes, set if limit granularity is 4Kb pages
|
||||||
BASE2431: 0xff00
|
BASE2431: 0xff00
|
||||||
},
|
},
|
||||||
INVALID: 0 // use X86.DESC.INVALID for invalid DESC values
|
INVALID: 0 // use X86.DESC.INVALID for invalid DESC values
|
||||||
|
|
|
||||||
|
|
@ -3197,18 +3197,6 @@ X86CPU.prototype.getIPDisp = function()
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* getIPDispWord()
|
|
||||||
*
|
|
||||||
* @this {X86CPU}
|
|
||||||
* @return {number} sign-extended value from the word at the current IP; IP advanced by 2 or 4
|
|
||||||
*/
|
|
||||||
X86CPU.prototype.getIPDispWord = function()
|
|
||||||
{
|
|
||||||
var w = this.getIPWord();
|
|
||||||
return (this.dataSize == 2? ((w << 16) >> 16) : w);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getSIBAddr(mod)
|
* getSIBAddr(mod)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,23 @@ X86.opMOVcr = function MOVcr()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: The following 16 new conditional jumps actually rely on the OPERAND override setting
|
||||||
|
* for determining whether a signed 16-bit or 32-bit displacement will be fetched, even though
|
||||||
|
* the ADDRESS override might seem more intuitive. Think of them as instructions that are loading
|
||||||
|
* a new operand into IP/EIP.
|
||||||
|
*
|
||||||
|
* Also, in 16-bit code, even though a signed rel16 value would seem to imply a range of -32768
|
||||||
|
* to +32767, any location within a 64Kb code segment outside that range can be reached by choosing
|
||||||
|
* a displacement in the opposite direction, causing the 16-bit value in EIP to underflow or overflow;
|
||||||
|
* any underflow or overflow doesn't matter, because only the low 16 bits of EIP are used when a
|
||||||
|
* 16-bit OPERAND size is in effect.
|
||||||
|
*
|
||||||
|
* In fact, for 16-bit jumps, it's simpler to always think of rel16 as an UNSIGNED value added to
|
||||||
|
* the current EIP, where the result is then truncated to a 16-bit value. This is why we don't have
|
||||||
|
* to sign-extend rel16 before adding it to the current EIP.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* opJOw()
|
* opJOw()
|
||||||
*
|
*
|
||||||
|
|
@ -351,7 +368,7 @@ X86.opMOVcr = function MOVcr()
|
||||||
*/
|
*/
|
||||||
X86.opJOw = function JOw()
|
X86.opJOw = function JOw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getOF()) {
|
if (this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -369,7 +386,7 @@ X86.opJOw = function JOw()
|
||||||
*/
|
*/
|
||||||
X86.opJNOw = function JNOw()
|
X86.opJNOw = function JNOw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getOF()) {
|
if (!this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -387,7 +404,7 @@ X86.opJNOw = function JNOw()
|
||||||
*/
|
*/
|
||||||
X86.opJCw = function JCw()
|
X86.opJCw = function JCw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getCF()) {
|
if (this.getCF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -405,7 +422,7 @@ X86.opJCw = function JCw()
|
||||||
*/
|
*/
|
||||||
X86.opJNCw = function JNCw()
|
X86.opJNCw = function JNCw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getCF()) {
|
if (!this.getCF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -423,7 +440,7 @@ X86.opJNCw = function JNCw()
|
||||||
*/
|
*/
|
||||||
X86.opJZw = function JZw()
|
X86.opJZw = function JZw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getZF()) {
|
if (this.getZF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -441,7 +458,7 @@ X86.opJZw = function JZw()
|
||||||
*/
|
*/
|
||||||
X86.opJNZw = function JNZw()
|
X86.opJNZw = function JNZw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getZF()) {
|
if (!this.getZF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -459,7 +476,7 @@ X86.opJNZw = function JNZw()
|
||||||
*/
|
*/
|
||||||
X86.opJBEw = function JBEw()
|
X86.opJBEw = function JBEw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getCF() || this.getZF()) {
|
if (this.getCF() || this.getZF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -477,7 +494,7 @@ X86.opJBEw = function JBEw()
|
||||||
*/
|
*/
|
||||||
X86.opJNBEw = function JNBEw()
|
X86.opJNBEw = function JNBEw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getCF() && !this.getZF()) {
|
if (!this.getCF() && !this.getZF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -495,7 +512,7 @@ X86.opJNBEw = function JNBEw()
|
||||||
*/
|
*/
|
||||||
X86.opJSw = function JSw()
|
X86.opJSw = function JSw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getSF()) {
|
if (this.getSF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -513,7 +530,7 @@ X86.opJSw = function JSw()
|
||||||
*/
|
*/
|
||||||
X86.opJNSw = function JNSw()
|
X86.opJNSw = function JNSw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getSF()) {
|
if (!this.getSF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -531,7 +548,7 @@ X86.opJNSw = function JNSw()
|
||||||
*/
|
*/
|
||||||
X86.opJPw = function JPw()
|
X86.opJPw = function JPw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getPF()) {
|
if (this.getPF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -549,7 +566,7 @@ X86.opJPw = function JPw()
|
||||||
*/
|
*/
|
||||||
X86.opJNPw = function JNPw()
|
X86.opJNPw = function JNPw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getPF()) {
|
if (!this.getPF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -567,7 +584,7 @@ X86.opJNPw = function JNPw()
|
||||||
*/
|
*/
|
||||||
X86.opJLw = function JLw()
|
X86.opJLw = function JLw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getSF() != !this.getOF()) {
|
if (!this.getSF() != !this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -585,7 +602,7 @@ X86.opJLw = function JLw()
|
||||||
*/
|
*/
|
||||||
X86.opJNLw = function JNLw()
|
X86.opJNLw = function JNLw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getSF() == !this.getOF()) {
|
if (!this.getSF() == !this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -603,7 +620,7 @@ X86.opJNLw = function JNLw()
|
||||||
*/
|
*/
|
||||||
X86.opJLEw = function JLEw()
|
X86.opJLEw = function JLEw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (this.getZF() || !this.getSF() != !this.getOF()) {
|
if (this.getZF() || !this.getSF() != !this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -621,7 +638,7 @@ X86.opJLEw = function JLEw()
|
||||||
*/
|
*/
|
||||||
X86.opJNLEw = function JNLEw()
|
X86.opJNLEw = function JNLEw()
|
||||||
{
|
{
|
||||||
var disp = this.getIPDispWord();
|
var disp = this.getIPWord();
|
||||||
if (!this.getZF() && !this.getSF() == !this.getOF()) {
|
if (!this.getZF() && !this.getSF() == !this.getOF()) {
|
||||||
this.setIP(this.getIP() + disp);
|
this.setIP(this.getIP() + disp);
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
|
||||||
|
|
@ -1301,7 +1318,7 @@ X86.aOps0F[0x06] = X86.opCLTS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On all processors (except the 8086/8088, of course), X86.OPCODE.UD2 (0x0F,0x0B), aka "UD2", is an
|
* On all processors (except the 8086/8088, of course), X86.OPCODE.UD2 (0x0F,0x0B), aka "UD2", is an
|
||||||
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all future x86 processors.
|
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all post-8086 processors.
|
||||||
*/
|
*/
|
||||||
X86.aOps0F[0x0B] = X86.opInvalid;
|
X86.aOps0F[0x0B] = X86.opInvalid;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3497,6 +3497,10 @@ X86.opESC = function ESC()
|
||||||
/**
|
/**
|
||||||
* op=0xE0 (LOOPNZ disp)
|
* op=0xE0 (LOOPNZ disp)
|
||||||
*
|
*
|
||||||
|
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
|
||||||
|
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
|
||||||
|
* even though it seems counter-intuitive; ditto for the REP prefix.
|
||||||
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
X86.opLOOPNZ = function LOOPNZ()
|
X86.opLOOPNZ = function LOOPNZ()
|
||||||
|
|
@ -3513,6 +3517,10 @@ X86.opLOOPNZ = function LOOPNZ()
|
||||||
/**
|
/**
|
||||||
* op=0xE1 (LOOPZ disp)
|
* op=0xE1 (LOOPZ disp)
|
||||||
*
|
*
|
||||||
|
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
|
||||||
|
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
|
||||||
|
* even though it seems counter-intuitive; ditto for the REP prefix.
|
||||||
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
X86.opLOOPZ = function LOOPZ()
|
X86.opLOOPZ = function LOOPZ()
|
||||||
|
|
@ -3529,6 +3537,10 @@ X86.opLOOPZ = function LOOPZ()
|
||||||
/**
|
/**
|
||||||
* op=0xE2 (LOOP disp)
|
* op=0xE2 (LOOP disp)
|
||||||
*
|
*
|
||||||
|
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
|
||||||
|
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
|
||||||
|
* even though it seems counter-intuitive; ditto for the REP prefix.
|
||||||
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
X86.opLOOP = function LOOP()
|
X86.opLOOP = function LOOP()
|
||||||
|
|
@ -3543,7 +3555,11 @@ X86.opLOOP = function LOOP()
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* op=0xE3 (JCXZ disp)
|
* op=0xE3 (JCXZ/JECXZ disp)
|
||||||
|
*
|
||||||
|
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
|
||||||
|
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
|
||||||
|
* even though it seems counter-intuitive; ditto for the REP prefix.
|
||||||
*
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -588,7 +588,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
if (I386 && cpu.model >= X86.MODEL_80386) {
|
if (I386 && cpu.model >= X86.MODEL_80386) {
|
||||||
base |= (ext & X86.DESC.EXT.BASE2431) << 16;
|
base |= (ext & X86.DESC.EXT.BASE2431) << 16;
|
||||||
limit |= (ext & X86.DESC.EXT.LIMIT1619) << 16;
|
limit |= (ext & X86.DESC.EXT.LIMIT1619) << 16;
|
||||||
if (ext & X86.DESC.EXT.GRANULARITY) limit = (limit << 12) | 0xfff;
|
if (ext & X86.DESC.EXT.LIMITPAGES) limit = (limit << 12) | 0xfff;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
all: tests.json
|
all: tests.json
|
||||||
|
|
||||||
tests.rom: tests.nasm
|
tests.com: tests.nasm
|
||||||
nasm -f bin tests.nasm -l tests.lst -o tests.rom
|
nasm -f bin tests.nasm -l tests.lst -o tests.com
|
||||||
|
|
||||||
tests.json: tests.rom
|
tests.json: tests.com
|
||||||
node ../../../modules/filedump/bin/filedump --file=tests.rom --output=tests.json --overwrite
|
node ../../../modules/filedump/bin/filedump --file=tests.com --output=tests.json --overwrite
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,85 @@
|
||||||
cpu 386
|
cpu 386
|
||||||
|
;
|
||||||
org 0x0000
|
; This file is designed to run as a ROM replacement, but it has a .COM extension because it's
|
||||||
|
; also designed to run as a COM file under DOS (hence the "org 0x100").
|
||||||
|
;
|
||||||
|
org 0x100
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
bits 16
|
bits 16
|
||||||
|
|
||||||
|
DPL0 equ 0
|
||||||
|
DPL1 equ 1
|
||||||
|
DPL2 equ 2
|
||||||
|
DPL3 equ 3
|
||||||
|
|
||||||
|
ACC_TYPE_SEG equ 0x1000
|
||||||
|
ACC_TYPE_CODE equ 0x0800
|
||||||
|
ACC_TYPE_READABLE equ 0x0200
|
||||||
|
ACC_TYPE_WRITABLE equ 0x0200
|
||||||
|
ACC_TYPE_CODE_READABLE equ 0x1a00
|
||||||
|
ACC_TYPE_DATA_WRITABLE equ 0x1200
|
||||||
|
|
||||||
|
EXT_BIG equ 0x0040
|
||||||
|
|
||||||
|
SEG_CODE_REAL equ 0xf000
|
||||||
|
SEG_CODE_PROT equ 0x0008
|
||||||
|
SEG_DATA_PROT equ 0x0010
|
||||||
|
|
||||||
|
CR0_MSW_PE equ 0x0001
|
||||||
|
|
||||||
|
;
|
||||||
|
; descDT defines a descriptor, given a base (%1), limit (%2), type (%3), dpl (%4), and bigness (%5)
|
||||||
|
;
|
||||||
|
%macro defDesc 1-5 0,0,0,0
|
||||||
|
dw (%2 & 0x0000ffff)
|
||||||
|
dw (%1 & 0x0000ffff)
|
||||||
|
dw ((%1 & 0x00ff0000) >> 16) | %3 | (%4 << 13)
|
||||||
|
dw ((%2 & 0x000f0000) >> 16) | %5 | ((%1 & 0xff000000) >> 16)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
|
||||||
start: mov eax,0x44332211
|
start: mov eax,0x44332211
|
||||||
mov ecx,0x88776655
|
mov ecx,0x88776655
|
||||||
mul ecx
|
mul ecx
|
||||||
div ecx
|
div ecx
|
||||||
|
jnz near goProt
|
||||||
|
|
||||||
call dword 0xf000:start
|
times 32768 nop
|
||||||
|
|
||||||
times 0xfff0-($-$$) nop
|
romGDT: defDesc 0
|
||||||
|
defDesc 0x000f0000,0x0000ffff,ACC_TYPE_CODE_READABLE,0
|
||||||
|
defDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE,0
|
||||||
|
|
||||||
|
goProt: lgdt [cs:romGDT]
|
||||||
|
mov eax,cr0
|
||||||
|
or eax,CR0_MSW_PE
|
||||||
|
mov cr0,eax
|
||||||
|
jmp dword SEG_CODE_PROT:inProt
|
||||||
|
|
||||||
|
inProt: mov ax,SEG_DATA_PROT
|
||||||
|
mov ds,ax
|
||||||
|
;
|
||||||
|
; Do some protected-mode tests...
|
||||||
|
;
|
||||||
|
|
||||||
|
goReal: mov eax,cr0
|
||||||
|
and eax,~CR0_MSW_PE
|
||||||
|
mov cr0,eax
|
||||||
|
jmp dword SEG_CODE_REAL:inReal
|
||||||
|
|
||||||
|
inReal: or eax,1
|
||||||
|
jnz start
|
||||||
|
|
||||||
|
;
|
||||||
|
; Fill the remaining space with NOPs until we get to target offset 0xFFF0.
|
||||||
|
;
|
||||||
|
; Note that we subtract 0x100 from the target offset because we're ORG'ed at 0x100.
|
||||||
|
;
|
||||||
|
times 0xfff0-0x100-($-$$) nop
|
||||||
|
|
||||||
bits 16
|
bits 16
|
||||||
jmp 0xf000:start
|
jmp SEG_CODE_REAL:start
|
||||||
|
|
||||||
db 0x20
|
db 0x20
|
||||||
db '04/04/15'
|
db '04/04/15'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue