PDA

View Full Version : Some kind of comparison error...!?!?



commodorejohn
September 30th, 2010, 04:44 PM
Okay, I've been trying to figure this one out for a good while now. I've been trying to put together a simple routine to draw a 16x16 tile to screen in Tandy/PCjr format (320x200 4-bit chunky pixel with 4-line interleave, specifically.) I've got it to the point where it's almost producing intelligible results, except that for some reason, the code to handle looping back to the low 8KB of screen memory (to handle the interleave) never gets called. Either I'm missing something, or the emu8086 instruction-set documentation is lying, because in emu8086, DOSBox, and PCEm, it will run right past branches it should obviously be taking. Here's the code:

drawTile: ; DS:SI = address of tile, ES:DI = address of position in screen memory
push cx
push si
push di
; for now, at least, the code assumes no X-scroll offset and drawing the whole tile
mov cx, 0x0010 ; our loop counter
.l1 movsw ; just copy that sucker into place!
movsw
movsw
movsw
add di, 0x1ff8 ; go to the next line
cmp di, 0x7f40 ; if we've gone too far, fix DI
jge .fx
loop .l1
pop di
pop si
pop cx
ret
.fx sub di, 0x7eb8 ; loop around to the next line at the beginning of screen memory
loop .l1
As you can see, the procedure is to use MOVSW to copy 8 bytes (one line,) add 8184 to bring it back to the starting X position on the next display line (which, thanks to the interleave, is 8192 bytes forward,) and check to make sure it didn't run past the end of screen memory. Everything works fine except for the check. The CMP instruction even appears to set the flags correctly in emu8086 (SF is set to 0, which the emu8086 reference says is the condition for branching with JGE,) but it never takes the branch. Is there something I'm missing here, or is the emu8086 reference mistaken on how the JGE instruction works? I'm at a loss to explain this.

Chuck(G)
September 30th, 2010, 05:16 PM
Okay, let's see what happens here. Each iteration through the loop at .ll gets to the CMP instruction with DI equal to 2000h, 4000h, 6000h, 8000h, where you're expecting it to take the branch. But let's do the arithmetic. 8000h - 7f40h = C0h, with no carry, plus, and not equal--but the overflow flag is set, since you're subtracting a positive number from a large negative one (8000h) and getting a positive result. Since JGE only jumps if OF=SF=0, the program doesn't.

The solution is to use an unsigned jump--JAE, not the signed JGE.

commodorejohn
September 30th, 2010, 05:29 PM
Ah. The emu8086 reference wasn't particularily clear on that. Still needs work, but that's the big stumbling block out of the way. Thanks!