87 lines
3.3 KiB
Plaintext
87 lines
3.3 KiB
Plaintext
NEC V20/V30 Bug
|
|
Howard Vigorita
|
|
New York Amateur Computer Club
|
|
|
|
I recently saw a message from Jonathan Platt on a Florida bulletin
|
|
board which mentioned rumors of a bug in the NEC V20/V30 processor.
|
|
For those of you that are interested, I've documented the bug below
|
|
using a V30 chip. Basically, the NEC chips fail to implement the 2
|
|
byte version of the POP instruction. This is not a serious bug;
|
|
the Intel register PUSH & POP instructions are duplicated in two
|
|
sets of instructions and all the assemblers and compilers I've seen
|
|
default to the shorter single byte set in favor of the two byte
|
|
set.
|
|
|
|
For those unfamiliar with the longer PUSH/POP form, the two byte
|
|
form of the PUSH (which works) will be shown first. The 'debug'
|
|
program is fed input from the 'testpush' file. The AX register is
|
|
loaded with FFFF hex, pushed onto the stack with the two byte PUSH,
|
|
then POPed into the CX register with the single byte POP opcode.
|
|
Note that the two byte PUSH is entered using a DB to load in the
|
|
FFF0 opcode. The '-u' command issued below shows that although
|
|
debug's '-a' command defaults to the short form POP, the long form
|
|
is interpreted properly when encountered.
|
|
|
|
A>debug < testpush
|
|
|
|
-a 100
|
|
|
|
0A7F:0100 mov ax,ffff
|
|
0A7F:0103 db ff,f0
|
|
0A7F:0105 pop cx
|
|
0A7F:0106 nop
|
|
0A7F:0107
|
|
|
|
-u 100,106
|
|
|
|
0A7F:0100 B8FFFF MOV AX,FFFF
|
|
0A7F:0103 FFF0 PUSH AX
|
|
0A7F:0105 59 POP CX
|
|
0A7F:0106 90 NOP
|
|
|
|
-g =100 106
|
|
|
|
AX=FFFF BX=0000 CX=FFFF DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
|
|
DS=0A7F ES=0A7F SS=0A7F CS=0A7F IP=0106 NV UP DI PL NZ NA PO NC
|
|
0A7F:0106 90 NOP
|
|
|
|
-q
|
|
|
|
The CX register ended up with FFFF hex as expected.
|
|
|
|
But the inverse operation does not work on the NEC chip. Below, 'testpop'
|
|
feeds input to 'debug'. The AX register is loaded with FFFF, a one byte
|
|
opcode PUSH AX is done, followed by the two byte form of the POP into CX.
|
|
Again, the two byte POP is implemented by DB'ing its 8FC1 opcode. Although
|
|
the SP register (stack pointer) is properly adjusted by the POP, the FFFF
|
|
hex does not end up in CX as it should:
|
|
|
|
A>debug < testpop
|
|
|
|
-a 100
|
|
|
|
0A7F:0100 mov ax,ffff
|
|
0A7F:0103 push ax
|
|
0A7F:0104 db 8f,c1
|
|
0A7F:0106 nop
|
|
0A7F:0107
|
|
|
|
-u 100,106
|
|
|
|
0A7F:0100 B8FFFF MOV AX,FFFF
|
|
0A7F:0103 50 PUSH AX
|
|
0A7F:0104 8FC1 POP CX
|
|
0A7F:0106 90 NOP
|
|
|
|
-g =100 106
|
|
|
|
AX=FFFF BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
|
|
DS=0A7F ES=0A7F SS=0A7F CS=0A7F IP=0106 NV UP DI PL NZ NA PO NC
|
|
0A7F:0106 90 NOP
|
|
|
|
-q
|
|
|
|
The above 'feature' can be exploited in distinguishing between NEC and
|
|
Intel chips. It is much simpler than the technique of issuing a unique
|
|
NEC instruction and intercepting the error trap interrupt.
|
|
|