Boriel Basic Forum
Variable corruption? - Printable Version

+- Boriel Basic Forum (https://forum.boriel.com)
+-- Forum: Compilers and Computer Languages (https://forum.boriel.com/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://forum.boriel.com/forumdisplay.php?fid=11)
+---- Forum: Help & Support (https://forum.boriel.com/forumdisplay.php?fid=16)
+---- Thread: Variable corruption? (/showthread.php?tid=587)



Variable corruption? - britlion - 2014-03-23

Code:
SUB FZXPrintAt(Y as uByte, X as uByte, printData as String) DIM FZXi as uInteger=0 PRINT INK 0;FZXi: PAUSE 0 FZXPrintAChar(22) 'at PRINT INK 1;FZXi: PAUSE 0 FZXPrintAChar(Y) PRINT INK 2;FZXi: PAUSE 0 FZXPrintAChar(X) PRINT INK 3;FZXi: PAUSE 0 PRINT LEN printData FOR FZXi=0 to LEN printData-1 PRINT INK 4;FZXi: PAUSE 0 FZXPrintAChar(CODE printData(FZXi)) PRINT INK 5;FZXi: PAUSE 0 NEXT FZXi END SUB

The first 3 calls to FZXPrintAChar work perfectly. Then we get to the loop part. It prints out 0 for FZXi and then prints the first letter of the string. Next time around the loop, FZXi becomes 33633!
But I'm not sure where?

Should I assume FZXPrintAChar does some stack corruption? This is just FZX from Einar Saukas (and friends) - and seems to work perfectly when called to print a single character. Even multiple times. But when looping, strange things happen.

The odd thing is it just seems to happen once. If I change the code to FZXPrintAChar(65) - it happily prints out letter A's in sequence beautifully. Except the first time through the loop, FZXi is set to 33633. It then proceeds to count upwards through 33634 33635 etc, as you'd expect for a loop variable.

Investigating as I type:
If I set the variable type to be a uByte, it gets set to 131 in the loop. (Which makes some sense, as the high byte of 33633 is 131 ) - but it isn't reset each time to 131, but is allowed to count upwards.

2 AM.

Time to quit for the night. Code dumped to <deleted> for the moment. - I fully accept the issue might be with the assembly module from someone else I've used!

EDIT: I think I see it. It's using IX in the routine. That will have to be changed!


Re: Variable corruption? - britlion - 2014-03-23

First Third pass, if you'd like to do testing:

(you'll also need an FXZ font; incbin at @FONT in asm context)

Code:
SUB FZXSetFont (FontAddress as uInteger) POKE UINTEGER @FZXFontPointer+1,FontAddress RETURN END SUB SUB FZXPrintAt(Y as uByte, X as uByte, printData as String) DIM FZXi as uByte=0 FZXPrintAChar(22) 'at FZXPrintAChar(Y) FZXPrintAChar(X) IF LEN printData > 0 THEN FOR FZXi=0 to LEN printData-1 FZXPrintAChar(CODE printData(FZXi)) NEXT FZXi END IF END SUB SUB FZXPrint(printData as String) DIM FZXi as uInteger IF LEN printData > 0 THEN FOR FZXi=0 to LEN printData-1 FZXPrintAChar(CODE printData(FZXi)) NEXT FZXi END IF END SUB SUB FASTCALL FZXPrintAChar (character as uByte) ASM PUSH IX CALL FZX_START POP IX RET ; ----------------------------------------------------------------------------- ; FZX driver - Copyright (c) 2013 Einar Saukas ; ----------------------------------------------------------------------------- ; org 65000 ; driver address ;FONT EQU 60000 ; font address MARGIN EQU 0 ; left margin (in pixels) ;STR_NUM EQU 4 ; stream #4 ; ----------------------------------------------------------------------------- ; CREATE CHANNEL AND ATTACH STREAM DRIVER: ; ld hl, ($5c53) ; store system variable PROG in HL ; dec hl ; ld bc, 5 ; allocate 5 bytes for channel below BASIC area ; push bc ; call $1655 ; call routine MAKE-ROOM ; pop bc ; ld hl, CH_DATA + 4 ; lddr ; copy CH_DATA to new channel space ; ld hl, ($5c4f) ; store system variable CHANS in HL ; ex de, hl ; inc hl ; inc hl ; now HL = allocated address + 1 ; sbc hl, de ; calculate offset between start of channels ; ; area and start of the new channel space ; ; (notice the carry flag was already cleared ; ; from executing CALL $1655 earlier) ; ld (STR_OFF), hl ; attach stream by storing channel address ; ; offset in streams table ; ret ;STR_OFF EQU $5c10+((STR_NUM+3)*2) ; address of channel offset in streams table ;CH_DATA: ; defw START ; address of the PRINT # routine ; defw $15c4 ; address of the INPUT # routine ; defb 'S' ; channel type 'S' ; ----------------------------------------------------------------------------- ; PROPORTIONAL PRINT ROUTINE FZX_START: ld hl, FZX_P_FLAG ; initial address of local variables dec (hl) ; check P_FLAG value by decrementing it jp m, CHK_AT ; expecting a regular character? jr z, GET_COL ; expecting the AT column? GET_LIN: cpl add a, 192 ; now A = 191 - char inc hl GET_COL: inc hl ld (hl), a ret CHK_AT: cp 22 ; specified keyword 'AT'? jr nz, CHK_CR ld (hl), 2 ; change P_FLAG to expect line value next time RET CHK_CR: inc (hl) ; increment P_FLAG to restore previous value inc hl END ASM FZXFontPointer: ASM ld bc, FONT push bc pop ix cp 13 jp z, NEWLINE CHK_CHAR: dec a ; now A = char - 1 cp (ix+2) ; compare with lastchar jr nc, UNDEF_CHAR sub 31 ; now A = char - 32 jr nc, PRINT_CHAR UNDEF_CHAR: ld a, '?'-32 ; print '?' instead of invalid character PRINT_CHAR: inc a ; now A = char - 31 ld l, a ld h, 0 ld d, h ld e, l add hl, hl add hl, de ; now HL = (char - 31) * 3 add hl, bc ; now HL references offset/kern in char table ld e, (hl) inc hl ld a, (hl) and 63 ld d, a ; now DE = offset xor (hl) rlca rlca ld c, a ; now C = kern push hl add hl, de dec hl ; now HL = char definition address ex (sp), hl ; now HL references offset/kern in char table inc hl ; now HL references shift/width in char table xor a rld ; now A = char shift push af rld ; now A = (width - 1) ld (WIDTH1+1), a cp 8 ; check if char width is larger than 8 bits rld ; restore char shift/width ld de, $000e ; same as "LD C,0" jr c, NARROW_CHAR ld de, $234e ; same as "LD C,(HL)" and "INC HL" NARROW_CHAR: ld (SMC), de ; self-modify code to handle narrow/large chars inc hl ; now HL references next char offset ld a, (hl) ; now A = LSB of next char offset add a, l ld e, a ; now E = LSB of next char definition address ld hl, FZX_P_COL ld a, (hl) sub c ; move left number of pixels specified by kern jr nc, ON_SCREEN ; stop moving if it would fall outside screen xor a ON_SCREEN: ld (hl), a ld a, (WIDTH1+1) ; now A = (width - 1) add a, (hl) ; now A = (width - 1) + column call c, NEWLINE ; if char width won't fit then move to new line ld bc, (FZX_P_COL) ld a, 1 sub (ix+0) ; now A = 1 - height add a, b ; now A = P_LIN - height + 1 jp nc, $0c86 ; call routine REPORT-5 ("Out of screen") pop af ; now A = shift add a, 191 ; range 0-191 call $22aa + 2 ; call PIXEL-ADD + 2 to calculate screen address ex af, af' ; now A' = (col % 8) jr CHK_LOOP MAIN_LOOP: ld d, (hl) ; now D = 1st byte from char definition grid inc hl ; next character definition SMC: ld c, (hl) ; now C = 2nd byte from char definition or zero inc hl ; (either "LD C,0" or "LD C,(HL)" + "INC HL") xor a ; now A = zero (since there's no 3rd byte) ex (sp), hl ; now HL = screen address ex af, af' ; now A = (col % 8), A' = 0 jr z, NO_ROTATE ld b, a ; now B = (col % 8) ex af, af' ; now A = 0, A' = (col % 8) ROTATE_PIXELS: srl d ; rotate right char definition grid in D,C,A rr c rra djnz ROTATE_PIXELS NO_ROTATE: inc l inc l or (hl) ld (hl), a ; put A on screen dec l ld a, c or (hl) ld (hl), a ; put C on screen dec l ld a, d or (hl) ld (hl), a ; put D on screen inc h ; move screen address by 1 pixel down ld a, h and 7 jr nz, CHK_LOOP ld a, l add a, 32 ld l, a jr c, CHK_LOOP ld a, h sub 8 ld h, a CHK_LOOP: ex (sp), hl ; now HL = char definition address ld a, l cp e ; check if reached next char definition address jr nz, MAIN_LOOP ; loop otherwise pop hl ; discard screen address from stack ld hl, FZX_P_COL ld a, (hl) ; now A = column WIDTH1: add a, 0 ; now A = column + (width - 1) scf adc a, (ix+1) ; now A = column + width + tracking jr nc, EXIT ; if didn't fall outside the screen then exit NEWLINE: ld (hl), MARGIN ; move to initial column at left margin inc hl ld a, (hl) ; now A = line sub (ix+0) ; now A = line - height EXIT: ld (hl), a ; move down a few pixels specified by height RET FZX_P_FLAG: defb 0 FZX_P_COL: defb MARGIN FZX_P_LIN: defb 191 FZX_END: ; ----------------------------------------------------------------------------- END ASM END SUB