Discussion:
Comparing to zero
(too old to reply)
luserdroog
2020-08-27 20:06:13 UTC
Permalink
Hi everyone,

I'm working on primitives for my newly working forth interpreter and I'm
having difficulty with comparisons 0= 0> and 0> . These each take a
number from the stack and push 0 or all-bits-1.

My code for 0= and 0> appear to be producing results, but I get the wrong
result for 0< even though it seems to follow appropriate parallel logic
as 0>. Any ideas? Does this suggest a bug in assembly or in my emulator?

CODE(0=, zeroeq, POP(AX),MOVCXI(1,0), CMP(,R,AX,CX), SBB(,R,AX,AX), PUSH(AX))
CODE(0>, zerogt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JL,3,MOVCXI(0xff,0xff), PUSH(CX))
CODE(0<, zerolt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JG,3,MOVCXI(0xff,0xff), PUSH(CX))

testing:
WORD(run, run, c_lit,0, c_zeroeq, c_dot,
c_lit,12, c_zerogt, c_dot,
c_lit,minus(50), c_zerolt, c_dot,
c_lit,79,c_emit, c_lit,75,c_emit, c_lit,5,c_double,c_emit, c_bye)

output:
$ ./a8086
110OK
luserdroog
2020-08-28 00:48:47 UTC
Permalink
Post by luserdroog
Hi everyone,
I'm working on primitives for my newly working forth interpreter and I'm
having difficulty with comparisons 0= 0> and 0> . These each take a
number from the stack and push 0 or all-bits-1.
My code for 0= and 0> appear to be producing results, but I get the wrong
result for 0< even though it seems to follow appropriate parallel logic
as 0>. Any ideas? Does this suggest a bug in assembly or in my emulator?
CODE(0=, zeroeq, POP(AX),MOVCXI(1,0), CMP(,R,AX,CX), SBB(,R,AX,AX), PUSH(AX))
CODE(0>, zerogt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JL,3,MOVCXI(0xff,0xff), PUSH(CX))
CODE(0<, zerolt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JG,3,MOVCXI(0xff,0xff), PUSH(CX))
WORD(run, run, c_lit,0, c_zeroeq, c_dot,
c_lit,12, c_zerogt, c_dot,
c_lit,minus(50), c_zerolt, c_dot,
c_lit,79,c_emit, c_lit,75,c_emit, c_lit,5,c_double,c_emit, c_bye)
$ ./a8086
110OK
I changed JL to JLE and JG to JGE. Still not right.
Here's a trace through zerogt.

ax:01f6 cx:0001 dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000 ip:01f8 fl:0004 NC NO NS NZ
58(130) popax:
ax:000c cx:0001 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01f9 fl:0004 NC NO NS NZ
b9(271) movcxi: 00(000) 00(000)
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01fc fl:0004 NC NO NS NZ
3b(073) cmpwt: c8(310) x:0 y:12 ->fffffff4
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01fe fl:0891 CA OV SN NZ
7e(176) jle: 03(003) <0>
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:0200 fl:0891 CA OV SN NZ
b9(271) movcxi: ff(377) ff(377)
ax:000c cx:ffff dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:0203 fl:0891 CA OV SN NZ
51(121) pushcx:
ax:000c cx:ffff dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000 ip:0204 fl:0891 CA OV SN NZ


It should be comparing 0 and 12, so it should take 0-12 and set
zf=0 sf=1 and of=1. Then JLE should jump if (sf^of)|zf which is 0.
And it seems to be doing all that. Maybe I'm just using CMP wrong?

The description from the 8086 family manual:

CMP destination,source
CMP (Compare) subtracts the source from the destination, which may be
bytes or words, but does not return the result. The operands are
unchanged, but the flags are updated and can be tested by a subsequent
conditional jump instruction. CMP updates AF, CF, OF, PF, SF and ZF.
The comparison reflected in the flags is that of the destination to
the source. IF a CMP instruction is followed by a JG (jump if greater)
instruction, for example, the jump is taken if the destination operand
is greater than the source operand.

So, in "CMP CX=0,AX=12" CX is the destination. So 0-12. Hmmm.
I still don't get it. But all the pieces seem to be here....
luserdroog
2020-08-28 06:22:02 UTC
Permalink
Post by luserdroog
Post by luserdroog
Hi everyone,
I'm working on primitives for my newly working forth interpreter and I'm
having difficulty with comparisons 0= 0> and 0> . These each take a
number from the stack and push 0 or all-bits-1.
My code for 0= and 0> appear to be producing results, but I get the wrong
result for 0< even though it seems to follow appropriate parallel logic
as 0>. Any ideas? Does this suggest a bug in assembly or in my emulator?
[snip]
Post by luserdroog
So, in "CMP CX=0,AX=12" CX is the destination. So 0-12. Hmmm.
I still don't get it. But all the pieces seem to be here....
I went to the fig-forth source and adapted that and now it appears
to be working.

CODE(0=, zeq, POP(AX), OR(,R,AX,AX), MOVAXI(0xff,0xff), JZ,2,INC_(R,AX), PUSH(AX))
CODE(0<, zless, POP(AX), OR(,R,AX,AX), MOVAXI(0xff,0xff), JL,2,INC_(R,AX), PUSH(AX))
CODE(0>, zmore, POP(AX), OR(,R,AX,AX), MOVAXI(0xff,0xff), JG,2,INC_(R,AX), PUSH(AX))
...
WORD(run, run, c_lit,0, c_zeq, c_dot,
c_lit,2, c_zeq, c_dot,
c_lit,12, c_zless, c_dot,
c_lit,1+(0xffff^50), c_zless, c_dot,
c_lit,12, c_zmore, c_dot,
c_lit,1+(0xffff^50), c_zmore, c_dot,
c_ok, c_bye)

$ !m
make a8086 CFLAGS='-g -Og'
cc -g -Og a8086.c -o a8086
$ !.
./a8086
100110OK

So the values all make sense now.
wolfgang kern
2020-08-28 06:27:54 UTC
Permalink
Post by luserdroog
Post by luserdroog
Hi everyone,
I'm working on primitives for my newly working forth interpreter and I'm
having difficulty with comparisons 0= 0> and 0> . These each take a
number from the stack and push 0 or all-bits-1.
My code for 0= and 0> appear to be producing results, but I get the wrong
result for 0< even though it seems to follow appropriate parallel logic
as 0>. Any ideas? Does this suggest a bug in assembly or in my emulator?
CODE(0=, zeroeq, POP(AX),MOVCXI(1,0), CMP(,R,AX,CX), SBB(,R,AX,AX), PUSH(AX))
CODE(0>, zerogt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JL,3,MOVCXI(0xff,0xff), PUSH(CX))
CODE(0<, zerolt, POP(AX),MOVCXI(0,0), CMP(,R,AX,CX), JG,3,MOVCXI(0xff,0xff), PUSH(CX))
WORD(run, run, c_lit,0, c_zeroeq, c_dot,
c_lit,12, c_zerogt, c_dot,
c_lit,minus(50), c_zerolt, c_dot,
c_lit,79,c_emit, c_lit,75,c_emit, c_lit,5,c_double,c_emit, c_bye)
$ ./a8086
110OK
I changed JL to JLE and JG to JGE. Still not right.
Here's a trace through zerogt.
ax:01f6 cx:0001 dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000 ip:01f8 fl:0004 NC NO NS NZ
ax:000c cx:0001 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01f9 fl:0004 NC NO NS NZ
b9(271) movcxi: 00(000) 00(000)
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01fc fl:0004 NC NO NS NZ
3b(073) cmpwt: c8(310) x:0 y:12 ->fffffff4
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:01fe fl:0891 CA OV SN NZ
7e(176) jle: 03(003) <0>
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:0200 fl:0891 CA OV SN NZ
b9(271) movcxi: ff(377) ff(377)
ax:000c cx:ffff dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000 ip:0203 fl:0891 CA OV SN NZ
ax:000c cx:ffff dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000 ip:0204 fl:0891 CA OV SN NZ
It should be comparing 0 and 12, so it should take 0-12 and set
zf=0 sf=1 and of=1. Then JLE should jump if (sf^of)|zf which is 0.
And it seems to be doing all that. Maybe I'm just using CMP wrong?
CMP destination,source
CMP (Compare) subtracts the source from the destination, which may be
bytes or words, but does not return the result. The operands are
unchanged, but the flags are updated and can be tested by a subsequent
conditional jump instruction. CMP updates AF, CF, OF, PF, SF and ZF.
The comparison reflected in the flags is that of the destination to
the source. IF a CMP instruction is followed by a JG (jump if greater)
instruction, for example, the jump is taken if the destination operand
is greater than the source operand.
So, in "CMP CX=0,AX=12" CX is the destination. So 0-12. Hmmm.
I still don't get it. But all the pieces seem to be here....
x86 Conditions:
O, NO
C, NC aka B, NB aka <, >=
Z, NZ aka E, NE aka =, <>
NA, A aka BE,NBE aka <=,> aka ZorC, aka NCNZ
S, NS aka -, +
PE, PO aka P, NP

L, NL aka NGE,GE aka <0,>=0
NG, G aka LE,NLE aka <=0, >0

only the last four and S/NS work signed
__
wolfgang
olcott
2020-08-30 18:45:50 UTC
Permalink
Post by luserdroog
Post by luserdroog
Hi everyone,
I'm working on primitives for my newly working forth interpreter and I'm
having difficulty with comparisons 0= 0> and 0> . These each take a
number from the stack and push 0 or all-bits-1.
My code for 0= and 0> appear to be producing results, but I get the wrong
result for 0< even though it seems to follow appropriate parallel logic
as 0>. Any ideas? Does this suggest a bug in assembly or in my emulator?
CODE(0=,     zeroeq,    POP(AX),MOVCXI(1,0), CMP(,R,AX,CX),
SBB(,R,AX,AX), PUSH(AX))
CODE(0>,     zerogt,    POP(AX),MOVCXI(0,0), CMP(,R,AX,CX),
JL,3,MOVCXI(0xff,0xff), PUSH(CX))
CODE(0<,     zerolt,    POP(AX),MOVCXI(0,0), CMP(,R,AX,CX),
JG,3,MOVCXI(0xff,0xff), PUSH(CX))
WORD(run,    run,       c_lit,0, c_zeroeq, c_dot,
                         c_lit,12, c_zerogt, c_dot,
                         c_lit,minus(50), c_zerolt, c_dot,
                         c_lit,79,c_emit, c_lit,75,c_emit,
c_lit,5,c_double,c_emit, c_bye)
$ ./a8086
110OK
I changed JL to JLE and JG to JGE. Still not right.
Here's a trace through zerogt.
ax:01f6 cx:0001 dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000
ip:01f8 fl:0004 NC NO NS NZ
ax:000c cx:0001 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000
ip:01f9 fl:0004 NC NO NS NZ
b9(271) movcxi: 00(000) 00(000)
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000
ip:01fc fl:0004 NC NO NS NZ
3b(073) cmpwt: c8(310) x:0 y:12 ->fffffff4
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000
ip:01fe fl:0891 CA OV SN NZ
7e(176) jle: 03(003) <0>
ax:000c cx:0000 dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000
ip:0200 fl:0891 CA OV SN NZ
b9(271) movcxi: ff(377) ff(377)
ax:000c cx:ffff dx:0030 bx:01f8 sp:1000 bp:2000 si:05ac di:0000
ip:0203 fl:0891 CA OV SN NZ
ax:000c cx:ffff dx:0030 bx:01f8 sp:0ffe bp:2000 si:05ac di:0000
ip:0204 fl:0891 CA OV SN NZ
It should be comparing 0 and 12, so it should take 0-12 and set
zf=0 sf=1 and of=1. Then JLE should jump if (sf^of)|zf which is 0.
And it seems to be doing all that. Maybe I'm just using CMP wrong?
CMP destination,source
CMP (Compare) subtracts the source from the destination, which may be
bytes or words, but does not return the result. The operands are
unchanged, but the flags are updated and can be tested by a subsequent
conditional jump instruction. CMP updates AF, CF, OF, PF, SF and ZF.
The comparison reflected in the flags is that of the destination to
the source. IF a CMP instruction is followed by a JG (jump if greater)
instruction, for example, the jump is taken if the destination operand
is greater than the source operand.
So, in "CMP CX=0,AX=12" CX is the destination. So 0-12. Hmmm.
I still don't get it. But all the pieces seem to be here....
O,  NO
C,  NC  aka B, NB    aka <, >=
Z,  NZ  aka E, NE    aka =, <>
NA, A   aka BE,NBE   aka <=,>   aka ZorC, aka NCNZ
S,  NS               aka -, +
PE, PO  aka P, NP
L,  NL  aka NGE,GE aka  <0,>=0
NG, G   aka LE,NLE aka <=0, >0
only the last four and S/NS work signed
__
wolfgang
test
--
Copyright 2020 Pete Olcott
Loading...