Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Print issues (*fixed*)
#1
Big issue: I notice print doesn't support commas.

Print "1","2" doesn't line up in columns. It won't even compile!

Print "1"+CHR$(6)+"2" does compile, but the print routine seems to ignore the tab.

I'm not sure how to work around this for spectrum programs that format text out in columns, or use commas to hop to the next line.



Optimization freak (I am. If I can save one assembler instruction, that's at least a byte saved!)

I notice that:

PRINT "1";
PRINT "2"

and PRINT "1";"2"

Produce exactly the same assembler code! Bravo. But

PRINT "1"+"2" is quite a lot shorter - the compiler sees it can combine the strings into one label.

Similarly:

PRINT INK1;"BLUE";INK 2;"RED"

is quite a lot longer in assembler than:

PRINT CHR$(16)+CHR$(1)+"BLUE"+CHR$(16)+CHR$(2)+"RED"

Your print routine parses both the above lines identically. The second, while far less decipherable to a human), to the compiler is a whole 14 bytes shorter in the assembler. Given how common print and combined color codes are in code, I suspect there is a notable size optimization that could be made in compiled code.


Off this post's topic:
The other one I noticed would be not storing a variable in a register if we don't need to:

Code:
LET A=A+1
LET A=A*2

Does Load, increment, store, multiply, store.

First up, I noticed it doesn't reload from store in the middle. It also recognizes multiply by two, and does the bitshift. That's very cool. It doesn't need to store in the middle tho!

(Is it worth optimizing double and triple bitshifts for *4 and *8 and so on? These are common multipliers, if only for screen coordinates.)
Reply
#2
britlion Wrote:Big issue: I notice print doesn't support commas.

Print "1","2" doesn't line up in columns. It won't even compile!

Print "1"+CHR$(6)+"2" does compile, but the print routine seems to ignore the tab.

I'm not sure how to work around this for spectrum programs that format text out in columns, or use commas to hop to the next line.
I forgot to implement the comma. Will try to implement it this evening.

Regarding the tab, it IS implemented (try TAB). If you want to use TAB with char codes, according to the ZX Spectrum manual, it is a 16 bit (two chars) sequence. So TAB 25 is: PRINT CHR$(6) + CHR$(25) + CHR$(0)

The apostrophe (') is also used in the ZX Spectrum, for "newline", but it won't be implemented, since that character is also used for comments. You will have to use CHR$(13) for that.

Quote:Optimization freak (I am. If I can save one assembler instruction, that's at least a byte saved!)

I notice that:

PRINT "1";
PRINT "2"

and PRINT "1";"2"

Produce exactly the same assembler code! Bravo. But

PRINT "1"+"2" is quite a lot shorter - the compiler sees it can combine the strings into one label.
True, the latter is preferable when dealing with constants. But the compiler recognizes *every* constant string, and tries a memory optimization for them, mapping the same string constants to the same memory location. Look:
Code:
PRINT "This is a string "; "Hello world"
PRINT "Hello world"
You could optimize this as :
Code:
PRINT "This is a string Hello world" + "Hello world"
But look what it gives in asm...

You will see that in the 1st example, the "Hello world" example has been "compressed". The compiler knows "Hello world" has been used twice and will compile it as if "Hello World" were something like:
Code:
CONST internal1$ = "Hello World" : REM Internal constant string
PRINT "This is a string "; internal1$
PRINT internal1$

Quote:Similarly:

PRINT INK1;"BLUE";INK 2;"RED"

is quite a lot longer in assembler than:

PRINT CHR$(16)+CHR$(1)+"BLUE"+CHR$(16)+CHR$(2)+"RED"

Your print routine parses both the above lines identically. The second, while far less decipherable to a human), to the compiler is a whole 14 bytes shorter in the assembler. Given how common print and combined color codes are in code, I suspect there is a notable size optimization that could be made in compiled code.
I will have a look to this. However, direct color codes should be a little faster (some t-states less).

Quote:Off this post's topic:
The other one I noticed would be not storing a variable in a register if we don't need to:

Code:
LET A=A+1
LET A=A*2

Does Load, increment, store, multiply, store.
Are you compiling with the -O3 (peephole optimization) flag? -O3 should do what you are suggesting
Quote:First up, I noticed it doesn't reload from store in the middle. It also recognizes multiply by two, and does the bitshift. That's very cool. It doesn't need to store in the middle tho!

(Is it worth optimizing double and triple bitshifts for *4 and *8 and so on? These are common multipliers, if only for screen coordinates.)
It should. Either for the division.
Reply
#3
boriel Wrote:[quote="britlion"]

Print "1"+CHR$(6)+"2" does compile, but the print routine seems to ignore the tab.

I forgot to implement the comma. Will try to implement it this evening.

Regarding the tab, it IS implemented (try TAB). If you want to use TAB with char codes, according to the ZX Spectrum manual, it is a 16 bit (two chars) sequence. So TAB 25 is: PRINT CHR$(6) + CHR$(25) + CHR$(0)

By tab here, I meant the comma tab - jump to mid screen. CHR$(6) should be the same as a comma - so for a spectrum

"1","2" is the same as "1";CHR$(6);"2"

The apostrophe (') is also used in the ZX Spectrum, for "newline", but it won't be implemented, since that character is also used for comments. You will have to use CHR$(13) for that.
[/quote]

Noticed that - but CHR$(13) prints just fine, so there's a workaround, there, at least.

Britlion Wrote:PRINT "1"+"2" is quite a lot shorter - the compiler sees it can combine the strings into one label.

True, the latter is preferable when dealing with constants. But the compiler recognizes *every* constant string, and tries a memory optimization for them, mapping the same string constants to the same memory location. Look:
Quote:Oh, very very clever. I know the java compiler does the exact same thing - every string literal is only used once. This can be handy.

Of course knowing how these are optimized, right now we can write code for size or speed. Hmm. Two different goals, there.

[quote]
I will have a look to this. However, direct color codes should be a little faster (some t-states less).

You are right, it is slightly:

Code:
FUNCTION t AS ULONG
    RETURN INT((65536 * PEEK (23674) + 256 * PEEK(23673) + PEEK (23672)))
END FUNCTION

PRINT at 0,0;t()

FOR N=1 TO 250
PRINT AT 10,10;CHR$(16)+CHR$(1)+"BLUE"+CHR$(16)+CHR$(2)+"RED"
NEXT N

PRINT at 1,0;t()

Takes 41 frames, as printed.

Code:
FUNCTION t AS ULONG
    RETURN INT((65536 * PEEK (23674) + 256 * PEEK(23673) + PEEK (23672)))
END FUNCTION

PRINT at 0,0;t()

FOR N=1 TO 250
PRINT AT 10,10;INK 1;"BLUE";INK 2;"RED"
NEXT N

PRINT at 1,0;t()

Takes 39!

Clearly traditional methods outweigh my clever ones. Bah!

Then again, we have speed vs size again!

boriel Wrote:[quote=Britlion]
Code:
LET A=A+1
LET A=A*2

Does Load, increment, store, multiply, store.

Boriel Wrote:Are you compiling with the -O3 (peephole optimization) flag? -O3 should do what you are suggesting

Code:
ld a, 10
    ld (_A), a
    inc a
    ld (_A), a
    sla a
    ld (_A), a

That's the key bit with -O3 - load, store, inc, store, multiply, store; yes?
Code:
E:\ZXBwork>zxb -A -O3 test.bas
INFO: __PRINTU8 is not defined. No optimization is done.
INFO: PRINT_EOL is not defined. No optimization is done.

E:\ZXBwork>

Not sure Optimization is working right for me. I get the above error messages.

britlion Wrote:(Is it worth optimizing double and triple bitshifts for *4 and *8 and so on? These are common multipliers, if only for screen coordinates.)
[quote="Boriel"]It should. Either for the division.
[/quote]

Awesome. This is one of the advantages of having a larger memory space for a compiler outside the spectrum - we can get far more code tweaks and optimizations in.
Reply
#4
There were other PRINT syntax issues. Like PRINT ;;; (syntactically correct) that weren't not supported.
Also PRINT (with no args) should print just a newline, but it was sometimes failing. Everything is now fixed (Thanks!).

The new version 1.1.7 is out!
Please, download an test it as much as possible, please :roll: I hope I haven't reintroduced other bugs while implementing/fixing other things.

TO DO:
  • STR$ and CHR$ need always parenthesis. This is hard to fix, as the IF <expr> THEN sentences... in a single line (a la Sinclair BASIC). Buy maybe, some day...
  • SAVE and LOAD for code and variables
  • READ/DATA/RESTORE (yes, it's somewhat possible)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)