test386 ready to run instruction tests under both DOS and Node.js now
This commit is contained in:
parent
464219a4c1
commit
635fc494c9
5 changed files with 142 additions and 73 deletions
|
|
@ -21,7 +21,7 @@
|
||||||
{ "id": "test386",
|
{ "id": "test386",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 983296,
|
"addr": 983296,
|
||||||
"size": 65280,
|
"size": 65276,
|
||||||
"alias": 4294902016,
|
"alias": 4294902016,
|
||||||
"file": "/tests/pc/80386/test386.json",
|
"file": "/tests/pc/80386/test386.json",
|
||||||
"notify": ""
|
"notify": ""
|
||||||
|
|
|
||||||
|
|
@ -7142,18 +7142,18 @@ if (DEBUGGER) {
|
||||||
case X86.OPCODE.LOOPZ:
|
case X86.OPCODE.LOOPZ:
|
||||||
case X86.OPCODE.LOOP:
|
case X86.OPCODE.LOOP:
|
||||||
this.nStep = nStep;
|
this.nStep = nStep;
|
||||||
this.incAddr(dbgAddr, 2);
|
this.incAddr(dbgAddr, dbgAddr.fData32? 4 : 2);
|
||||||
break;
|
break;
|
||||||
case X86.OPCODE.CALL:
|
case X86.OPCODE.CALL:
|
||||||
if (fCallStep) {
|
if (fCallStep) {
|
||||||
this.nStep = nStep;
|
this.nStep = nStep;
|
||||||
this.incAddr(dbgAddr, 3);
|
this.incAddr(dbgAddr, dbgAddr.fData32? 5 : 3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case X86.OPCODE.CALLF:
|
case X86.OPCODE.CALLF:
|
||||||
if (fCallStep) {
|
if (fCallStep) {
|
||||||
this.nStep = nStep;
|
this.nStep = nStep;
|
||||||
this.incAddr(dbgAddr, 5);
|
this.incAddr(dbgAddr, dbgAddr.fData32? 7 : 5);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case X86.OPCODE.GRP4W:
|
case X86.OPCODE.GRP4W:
|
||||||
|
|
@ -7202,8 +7202,8 @@ if (DEBUGGER) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* A successful run will ultimately call stop(), which will in turn call clearTempBreakpoint(),
|
* A successful run will ultimately call stop(), which will in turn call clearTempBreakpoint(),
|
||||||
* which will clear nStep, so there's your assurance that nStep will be reset. Now we may
|
* which will clear nStep, so there's your assurance that nStep will be reset. Now we may have
|
||||||
* have stopped for reasons unrelated to the temporary breakpoint, but that's OK.
|
* stopped for reasons unrelated to the temporary breakpoint, but that's OK.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
this.doTrace(fRegs? "tr" : "t");
|
this.doTrace(fRegs? "tr" : "t");
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ SerialPort.DL_DEFAULT = 0x180; // we select an arbitrary default Diviso
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receiver Buffer Register (RBR.REG, offset 0; eg, 0x3F8 or 0x2F8)
|
* Receiver Buffer Register (RBR.REG, offset 0; eg, 0x3F8 or 0x2F8) on read, Transmitter Holding Register on write
|
||||||
*/
|
*/
|
||||||
SerialPort.RBR = {REG: 0}; // (read)
|
SerialPort.RBR = {REG: 0}; // (read)
|
||||||
|
|
||||||
|
|
@ -805,11 +805,13 @@ SerialPort.prototype.echoByte = function(b)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.consoleOutput != null) {
|
if (this.consoleOutput != null) {
|
||||||
this.consoleOutput += String.fromCharCode(b);
|
|
||||||
if (b == 0x0A || this.consoleOutput.length >= 1024) {
|
if (b == 0x0A || this.consoleOutput.length >= 1024) {
|
||||||
this.println(str.trim(this.consoleOutput));
|
this.println(this.consoleOutput);
|
||||||
this.consoleOutput = "";
|
this.consoleOutput = "";
|
||||||
}
|
}
|
||||||
|
if (b != 0x0A) {
|
||||||
|
this.consoleOutput += String.fromCharCode(b);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
;
|
;
|
||||||
; Overview
|
; Overview
|
||||||
; --------
|
; --------
|
||||||
; This file is designed to run both as a test ROM and as a DOS COM file (hence the "org 0x100"),
|
; This file is designed to run both as a test ROM and as a DOS .COM file (hence the "org 0x100"),
|
||||||
; which is why it has a ".com" extension instead of the more typical ".rom" extension.
|
; which is why it has a ".com" extension instead of the more typical ".rom" extension.
|
||||||
;
|
;
|
||||||
; When used as a ROM, it should be installed at physical address 983296 (0xf0100) and aliased at
|
; When used as a ROM, it should be installed at physical address 983296 (0xf0100) and aliased at
|
||||||
|
|
@ -90,10 +90,15 @@ PAGING equ 1
|
||||||
; And in the second page (0x1000-0x1fff), we might build a page directory, followed by a single page table
|
; And in the second page (0x1000-0x1fff), we might build a page directory, followed by a single page table
|
||||||
; that allows us to map up to 4Mb (although we'd likely only create PTEs for the first 1Mb).
|
; that allows us to map up to 4Mb (although we'd likely only create PTEs for the first 1Mb).
|
||||||
;
|
;
|
||||||
|
; However, the code to do that is currently disabled (see %ifdef RAM_GDT), because it's just as easy to define
|
||||||
|
; the structures we need inside the .COM image and statically initialize them to the values assumed for ROM
|
||||||
|
; operation. For RAM operation, we tweak the structures as needed; the tweaks have no effect when loaded in ROM.
|
||||||
|
;
|
||||||
;RAM_GDT equ 0x0c00
|
;RAM_GDT equ 0x0c00
|
||||||
;RAM_IDTR equ 0x0d00
|
;RAM_IDTR equ 0x0d00
|
||||||
;RAM_GDTR equ 0x0d08
|
;RAM_GDTR equ 0x0d08
|
||||||
;RAM_RETF equ 0x0d10
|
;RAM_RETF equ 0x0d10
|
||||||
|
;
|
||||||
|
|
||||||
CSEG_REAL equ 0xf000
|
CSEG_REAL equ 0xf000
|
||||||
CSEG_PROT16 equ 0x0008
|
CSEG_PROT16 equ 0x0008
|
||||||
|
|
@ -135,6 +140,12 @@ SSEG_PROT32 equ 0x0028
|
||||||
|
|
||||||
start: nop
|
start: nop
|
||||||
;
|
;
|
||||||
|
; If we didn't CALL or PUSH anything on the stack AND we turned interrupts off, the top of our image would be
|
||||||
|
; safe, but if we're running in RAM, we do issue a few DOS calls before switching into protected-mode and onto
|
||||||
|
; a new stack, so we need to set SP to a safer location inside the .COM image.
|
||||||
|
;
|
||||||
|
mov sp,tempStack
|
||||||
|
;
|
||||||
; Quick test of unsigned 32-bit multiplication and division
|
; Quick test of unsigned 32-bit multiplication and division
|
||||||
;
|
;
|
||||||
mov eax,0x44332211
|
mov eax,0x44332211
|
||||||
|
|
@ -155,8 +166,8 @@ start: nop
|
||||||
jnz near error
|
jnz near error
|
||||||
|
|
||||||
jmp initGDT
|
jmp initGDT
|
||||||
times 32768 nop ; lots of NOPs to force a 16-bit conditional jump
|
times 32768 nop ; lots of NOPs to test generation of 16-bit conditional jumps
|
||||||
|
tempStack:
|
||||||
;
|
;
|
||||||
; storeDesc(EBX=base, ECX=limit, DX=type, AX=ext, DI=address of descriptor)
|
; storeDesc(EBX=base, ECX=limit, DX=type, AX=ext, DI=address of descriptor)
|
||||||
;
|
;
|
||||||
|
|
@ -211,7 +222,7 @@ initGDT:
|
||||||
mov word [RAM_RETF+2],cs
|
mov word [RAM_RETF+2],cs
|
||||||
%else
|
%else
|
||||||
;
|
;
|
||||||
; This code fixes the GDT and all our FAR jumps if we're running in RAM
|
; This code fixes the GDT and all our far jumps if we're running in RAM
|
||||||
;
|
;
|
||||||
xor eax,eax
|
xor eax,eax
|
||||||
mov ax,cs
|
mov ax,cs
|
||||||
|
|
@ -378,34 +389,34 @@ toProt32:
|
||||||
;
|
;
|
||||||
; Test moving a byte to a 32-bit register with sign-extension
|
; Test moving a byte to a 32-bit register with sign-extension
|
||||||
;
|
;
|
||||||
movsx eax,byte [cs:0xffff]
|
movsx eax,byte [cs:signedByte]
|
||||||
cmp eax,0xffffff80
|
cmp eax,0xffffff80
|
||||||
jne near error
|
jne near error
|
||||||
;
|
;
|
||||||
; Test moving a word to a 32-bit register with sign-extension
|
; Test moving a word to a 32-bit register with sign-extension
|
||||||
;
|
;
|
||||||
movsx eax,word [cs:0xfffe]
|
movsx eax,word [cs:signedWord]
|
||||||
cmp eax,0xffff80fc
|
cmp eax,0xffff8080
|
||||||
jne near error
|
jne near error
|
||||||
;
|
;
|
||||||
; Test moving a byte to a 32-bit register with zero-extension
|
; Test moving a byte to a 32-bit register with zero-extension
|
||||||
;
|
;
|
||||||
movzx eax,byte [cs:0xffff]
|
movzx eax,byte [cs:signedByte]
|
||||||
cmp eax,0x00000080
|
cmp eax,0x00000080
|
||||||
jne near error
|
jne near error
|
||||||
;
|
;
|
||||||
; Test moving a word to a 32-bit register with zero-extension
|
; Test moving a word to a 32-bit register with zero-extension
|
||||||
;
|
;
|
||||||
movzx eax,word [cs:0xfffe]
|
movzx eax,word [cs:signedWord]
|
||||||
cmp eax,0x000080fc
|
cmp eax,0x00008080
|
||||||
jne near error
|
jne near error
|
||||||
;
|
;
|
||||||
; More assorted ZX and SX tests
|
; More assorted zero and sign-extension tests
|
||||||
;
|
;
|
||||||
mov esp,0x40000
|
mov esp,0x40000
|
||||||
mov edx,[esp] ; save word at scratch address 0x40000
|
mov edx,[esp] ; save word at scratch address 0x40000
|
||||||
add esp,4
|
add esp,4
|
||||||
push byte -128 ; NASM refuses to use opcode 0x6A ("PUSH imm8") unless we specify "byte"
|
push byte -128 ; NASM will not use opcode 0x6A ("PUSH imm8") unless we specify "byte"
|
||||||
pop ebx ; verify EBX == 0xFFFFFF80
|
pop ebx ; verify EBX == 0xFFFFFF80
|
||||||
cmp ebx,0xFFFFFF80
|
cmp ebx,0xFFFFFF80
|
||||||
jne near error
|
jne near error
|
||||||
|
|
@ -492,27 +503,29 @@ toProt32:
|
||||||
;
|
;
|
||||||
; Now run a series of unverified opcode tests (verification will happen later, by comparing the output of the tests)
|
; Now run a series of unverified opcode tests (verification will happen later, by comparing the output of the tests)
|
||||||
;
|
;
|
||||||
int3
|
|
||||||
cld
|
cld
|
||||||
mov esi,tableOps ; ESI -> tableOps entry
|
mov esi,tableOps ; ESI -> tableOps entry
|
||||||
testOps:
|
testOps:
|
||||||
movzx ecx,byte [cs:esi] ; ECX == length of instruction sequence
|
movzx ecx,byte [cs:esi] ; ECX == length of instruction sequence
|
||||||
jecxz doneOps ; zero means we've reached the end of the table
|
test ecx,ecx ; (must use JZ since there's no long version of JECXZ)
|
||||||
|
jz near testDone ; zero means we've reached the end of the table
|
||||||
movzx ebx,byte [cs:esi+1] ; EBX == TYPE
|
movzx ebx,byte [cs:esi+1] ; EBX == TYPE
|
||||||
shl ebx,5 ; EBX == type * 32
|
shl ebx,5 ; EBX == TYPE * 32
|
||||||
movzx edx,byte [cs:esi+2] ; EDX == SIZE
|
movzx edx,byte [cs:esi+2] ; EDX == SIZE
|
||||||
lea ebx,[cs:typeValues+ebx+edx*8] ; EBX -> values for type
|
shl edx,4 ; EDX == SIZE * 16
|
||||||
|
lea ebx,[cs:typeValues+ebx+edx] ; EBX -> values for type
|
||||||
add esi,3 ; ESI -> instruction mnemonic
|
add esi,3 ; ESI -> instruction mnemonic
|
||||||
skipOp: cs lodsb
|
.skip: cs lodsb
|
||||||
test al,al
|
test al,al
|
||||||
jnz skipOp
|
jnz .skip
|
||||||
|
|
||||||
xor eax,eax ; set flags to known values prior tests
|
|
||||||
push ecx
|
push ecx
|
||||||
mov ecx,[cs:ebx] ; ECX == count of values for dst
|
mov ecx,[cs:ebx] ; ECX == count of values for dst
|
||||||
mov ebx,[cs:ebx+4] ; EBX -> values for dst
|
mov eax,[cs:ebx+4] ; EAX -> values for dst
|
||||||
mov ebp,ecx ; EBP == count of values for src
|
mov ebp,[cs:ebx+8] ; EBP == count of values for src
|
||||||
mov edi,ebx ; EDI -> values for src
|
mov edi,[cs:ebx+12] ; EDI -> values for src
|
||||||
|
xchg ebx,eax ; EBX -> values for dst
|
||||||
|
sub eax,eax ; set all ARITH flags to known values prior to tests
|
||||||
testDst:
|
testDst:
|
||||||
push ebp
|
push ebp
|
||||||
push edi
|
push edi
|
||||||
|
|
@ -545,7 +558,7 @@ testSrc:
|
||||||
add esi,ecx ; ESI -> next tableOps entry
|
add esi,ecx ; ESI -> next tableOps entry
|
||||||
jmp testOps
|
jmp testOps
|
||||||
|
|
||||||
doneOps:
|
testDone:
|
||||||
jmp doneProt
|
jmp doneProt
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
@ -558,11 +571,15 @@ doneOps:
|
||||||
printOp:
|
printOp:
|
||||||
pushfd
|
pushfd
|
||||||
pushad
|
pushad
|
||||||
findOp: dec esi
|
.findSize:
|
||||||
|
dec esi
|
||||||
mov al,[cs:esi-1]
|
mov al,[cs:esi-1]
|
||||||
cmp al,32
|
cmp al,32
|
||||||
jae findOp
|
jae .findSize
|
||||||
call printStr
|
call printStr
|
||||||
|
movzx eax,al
|
||||||
|
mov al,[cs:achSize+eax]
|
||||||
|
call printChar
|
||||||
mov al,' '
|
mov al,' '
|
||||||
call printChar
|
call printChar
|
||||||
popad
|
popad
|
||||||
|
|
@ -603,7 +620,7 @@ printEDX:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;
|
;
|
||||||
; printPS()
|
; printPS(ESI -> instruction sequence)
|
||||||
;
|
;
|
||||||
; Uses: None
|
; Uses: None
|
||||||
;
|
;
|
||||||
|
|
@ -611,10 +628,18 @@ printPS:
|
||||||
pushfd
|
pushfd
|
||||||
pushad
|
pushad
|
||||||
pushfd
|
pushfd
|
||||||
pop eax
|
pop edx
|
||||||
|
.findType:
|
||||||
|
dec esi
|
||||||
|
mov al,[cs:esi-1]
|
||||||
|
cmp al,32
|
||||||
|
jae .findType
|
||||||
|
movzx eax,byte [cs:esi-2]
|
||||||
|
and edx,[cs:typeMasks+eax*4]
|
||||||
mov esi,strPS
|
mov esi,strPS
|
||||||
call printStr
|
call printStr
|
||||||
mov cl,4
|
mov cl,4
|
||||||
|
mov eax,edx
|
||||||
call printVal
|
call printVal
|
||||||
popad
|
popad
|
||||||
popfd
|
popfd
|
||||||
|
|
@ -626,14 +651,12 @@ printPS:
|
||||||
; Uses: None
|
; Uses: None
|
||||||
;
|
;
|
||||||
printEOL:
|
printEOL:
|
||||||
pushfd
|
push eax
|
||||||
pushad
|
; mov al,0x0d
|
||||||
mov al,0x0d
|
; call printChar
|
||||||
call printChar
|
|
||||||
mov al,0x0a
|
mov al,0x0a
|
||||||
call printChar
|
call printChar
|
||||||
popad
|
pop eax
|
||||||
popfd
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
@ -642,10 +665,18 @@ printEOL:
|
||||||
; Uses: None
|
; Uses: None
|
||||||
;
|
;
|
||||||
printChar:
|
printChar:
|
||||||
|
pushfd
|
||||||
push edx
|
push edx
|
||||||
mov dx,0x2F8 ; EDX -> COM2 I/O port
|
push eax
|
||||||
|
mov dx,0x2FD ; EDX == COM2 LSR (Line Status Register)
|
||||||
|
.loop: in al,dx ;
|
||||||
|
test al,0x20 ; THR (Transmitter Holding Register) empty?
|
||||||
|
jz .loop ; no
|
||||||
|
pop eax
|
||||||
|
mov dx,0x2F8 ; EDX -> COM2 THR (Transmitter Holding Register)
|
||||||
out dx,al
|
out dx,al
|
||||||
pop edx
|
pop edx
|
||||||
|
popfd
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
@ -655,12 +686,12 @@ printChar:
|
||||||
;
|
;
|
||||||
printStr:
|
printStr:
|
||||||
push eax
|
push eax
|
||||||
psLoop: cs lodsb
|
.loop: cs lodsb
|
||||||
test al,al
|
test al,al
|
||||||
jz psDone
|
jz .done
|
||||||
call printChar
|
call printChar
|
||||||
jmp psLoop
|
jmp .loop
|
||||||
psDone: pop eax
|
.done: pop eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
@ -670,20 +701,20 @@ psDone: pop eax
|
||||||
;
|
;
|
||||||
printVal:
|
printVal:
|
||||||
shl cl,2 ; CL == number of bits (4 times the number of hex digits)
|
shl cl,2 ; CL == number of bits (4 times the number of hex digits)
|
||||||
jz pvDone
|
jz .done
|
||||||
pvLoop: sub cl,4
|
.loop: sub cl,4
|
||||||
push eax
|
push eax
|
||||||
shr eax,cl
|
shr eax,cl
|
||||||
and al,0x0f
|
and al,0x0f
|
||||||
add al,'0'
|
add al,'0'
|
||||||
cmp al,'9'
|
cmp al,'9'
|
||||||
jbe pvOK
|
jbe .digit
|
||||||
add al,'A'-'0'-10
|
add al,'A'-'0'-10
|
||||||
pvOK: call printChar
|
.digit: call printChar
|
||||||
pop eax
|
pop eax
|
||||||
test cl,cl
|
test cl,cl
|
||||||
jnz pvLoop
|
jnz .loop
|
||||||
pvDone: mov al,' '
|
.done: mov al,' '
|
||||||
call printChar
|
call printChar
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
@ -711,25 +742,36 @@ SIZE_LONG equ 2
|
||||||
strEAX: db "EAX=",0
|
strEAX: db "EAX=",0
|
||||||
strEDX: db "EDX=",0
|
strEDX: db "EDX=",0
|
||||||
strPS: db "PS=",0
|
strPS: db "PS=",0
|
||||||
|
achSize db "BWD"
|
||||||
|
|
||||||
tableOps:
|
tableOps:
|
||||||
defOp "ADD",ADD,AL,DL,TYPE_ARITH
|
defOp "ADD",add,al,dl,TYPE_ARITH
|
||||||
defOp "ADD",ADD,AX,DX,TYPE_ARITH
|
defOp "ADD",add,ax,dx,TYPE_ARITH
|
||||||
defOp "ADD",ADD,EAX,EDX,TYPE_ARITH
|
defOp "ADD",add,eax,edx,TYPE_ARITH
|
||||||
db 0
|
db 0
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
|
|
||||||
typeValues:
|
typeMasks:
|
||||||
dd 9,arithValues,18,arithValues,27,arithValues,0,0
|
dd PS_ARITH
|
||||||
|
|
||||||
arithValues:
|
arithValues:
|
||||||
dd 0x00,0x01,0x02,0x7E,0x7F,0x80,0x81,0xFE,0xFF
|
.bvals: dd 0x00,0x01,0x02,0x7E,0x7F,0x80,0x81,0xFE,0xFF
|
||||||
dd 0x0000,0x0001,0x0002,0x7FFE,0x7FFF,0x8000,0x8001,0xFFFE,0xFFFF
|
ARITH_BYTES equ ($-.bvals)/4
|
||||||
dd 0x00000000,0x00000001,0x00000002,0x7FFFFFFE,0x7FFFFFFF,0x80000000,0x80000001,0xFFFFFFFE,0xFFFFFFFF
|
|
||||||
|
|
||||||
error: int3
|
.wvals: dd 0x0000,0x0001,0x0002,0x7FFE,0x7FFF,0x8000,0x8001,0xFFFE,0xFFFF
|
||||||
jmp error
|
ARITH_WORDS equ ($-.wvals)/4
|
||||||
|
|
||||||
|
.dvals: dd 0x00000000,0x00000001,0x00000002,0x7FFFFFFE,0x7FFFFFFF,0x80000000,0x80000001,0xFFFFFFFE,0xFFFFFFFF
|
||||||
|
ARITH_DWORDS equ ($-.dvals)/4
|
||||||
|
|
||||||
|
typeValues:
|
||||||
|
dd ARITH_BYTES,arithValues,ARITH_BYTES,arithValues
|
||||||
|
dd ARITH_BYTES+ARITH_WORDS,arithValues,ARITH_BYTES+ARITH_WORDS,arithValues
|
||||||
|
dd ARITH_BYTES+ARITH_WORDS+ARITH_DWORDS,arithValues,ARITH_BYTES+ARITH_WORDS+ARITH_DWORDS,arithValues
|
||||||
|
dd 0,0
|
||||||
|
|
||||||
|
error: jmp error
|
||||||
|
|
||||||
doneProt:
|
doneProt:
|
||||||
mov ax,DSEG_PROT16
|
mov ax,DSEG_PROT16
|
||||||
|
|
@ -759,7 +801,7 @@ toReal:
|
||||||
mov sp,0xfffe
|
mov sp,0xfffe
|
||||||
|
|
||||||
cmp ax,CSEG_REAL ; is CS equal to 0xf000?
|
cmp ax,CSEG_REAL ; is CS equal to 0xf000?
|
||||||
je near jmpStart ; yes, so loop around, only because we have nowhere else to go
|
spin: je spin ; near jmpStart ; yes, so loop around, because we have nowhere else to go
|
||||||
int INT_DOSEXIT ; no, so assume we're running under DOS and exit
|
int INT_DOSEXIT ; no, so assume we're running under DOS and exit
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
@ -768,10 +810,24 @@ toReal:
|
||||||
;
|
;
|
||||||
times 0xfff0-0x100-($-$$) nop
|
times 0xfff0-0x100-($-$$) nop
|
||||||
|
|
||||||
jmpStart:
|
;
|
||||||
jmp CSEG_REAL:start
|
; Unfortunately, when PC-DOS 2.0 loads our .COM file, the last 4 bytes are not valid, in part because DOS must
|
||||||
|
; zero the last 2 bytes so that a near RET will return to the PSP's INT 0x20 and gracefully terminate the program.
|
||||||
|
; Newer versions of DOS simply refuse to load the file (the safest thing to do), claiming insufficient memory.
|
||||||
|
;
|
||||||
|
; To avoid these loading issues, I now omit the last 4 bytes from image, and it will still work as a ROM image as
|
||||||
|
; long as jmpStart is at offset 0xFFF0.
|
||||||
|
;
|
||||||
|
|
||||||
db 0x20
|
jmpStart:
|
||||||
db '04/04/15'
|
jmp CSEG_REAL:start ; 0000FFF0
|
||||||
db 0xFC ; 0000FFFE FC (Model ID byte)
|
signedWord:
|
||||||
db 0x80 ; 0000FFFF 80 (normally, location of a checksum byte)
|
db 0x80 ; 0000FFF5 80
|
||||||
|
signedByte:
|
||||||
|
db 0x80 ; 0000FFF6 80
|
||||||
|
signature:
|
||||||
|
db 'PCJS',0 ; 0000FFF7 "PCJS",0
|
||||||
|
; db 0x00 ; 0000FFFC 00
|
||||||
|
; db 0x00 ; 0000FFFD 00
|
||||||
|
; db 0xFC ; 0000FFFE FC (Model ID byte)
|
||||||
|
; db 0x00 ; 0000FFFF 00 (normally a checksum byte)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,20 @@
|
||||||
;
|
;
|
||||||
; X86.DESC defines (see x86.js)
|
; X86.DESC defines (see x86.js)
|
||||||
;
|
;
|
||||||
|
PS_CF equ 0x0001
|
||||||
|
PS_PF equ 0x0004
|
||||||
|
PS_AF equ 0x0010
|
||||||
|
PS_ZF equ 0x0040
|
||||||
|
PS_SF equ 0x0080
|
||||||
|
PS_TF equ 0x0100
|
||||||
|
PS_IF equ 0x0200
|
||||||
|
PS_DF equ 0x0400
|
||||||
|
PS_OF equ 0x0800
|
||||||
|
PS_ARITH equ (PS_CF | PS_PF | PS_AF | PS_ZF | PS_SF | PS_OF)
|
||||||
|
|
||||||
|
CR0_MSW_PE equ 0x0001
|
||||||
|
CR0_PG equ 0x80000000 ; set if paging enabled
|
||||||
|
|
||||||
ACC_TYPE_SEG equ 0x1000
|
ACC_TYPE_SEG equ 0x1000
|
||||||
ACC_PRESENT equ 0x8000
|
ACC_PRESENT equ 0x8000
|
||||||
ACC_TYPE_CODE equ 0x0800
|
ACC_TYPE_CODE equ 0x0800
|
||||||
|
|
@ -12,9 +26,6 @@ ACC_TYPE_DATA_WRITABLE equ 0x1200
|
||||||
EXT_NONE equ 0x0000
|
EXT_NONE equ 0x0000
|
||||||
EXT_BIG equ 0x0040
|
EXT_BIG equ 0x0040
|
||||||
|
|
||||||
CR0_MSW_PE equ 0x0001
|
|
||||||
CR0_PG equ 0x80000000 ; set if paging enabled
|
|
||||||
|
|
||||||
PTE_FRAME equ 0xfffff000
|
PTE_FRAME equ 0xfffff000
|
||||||
PTE_DIRTY equ 0x00000040 ; page has been modified
|
PTE_DIRTY equ 0x00000040 ; page has been modified
|
||||||
PTE_ACCESSED equ 0x00000020 ; page has been accessed
|
PTE_ACCESSED equ 0x00000020 ; page has been accessed
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue