long for newbie's

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

long for newbie's

Post by cborn »

Hello
i have a problem with printing the result of 'long' on screen. i just want to print the full number off FRAMES on ZX but i get strange output.
its part of a system variable list,

Code: Select all

unsigned char  *FRAMES1 = 23672 ;
printf("%6u FRAMES1=%6u\n",FRAMES1 , *FRAMES1 );
unsigned char  *FRAMES2 = 23673 ;
printf("%6u FRAMES2=%6u\n",FRAMES2 , *FRAMES2 );
unsigned char  *FRAMES3 = 23674 ;
printf("%6u FRAMES3=%6u\n",FRAMES3 , *FRAMES3 );
unsigned long frame3 = *FRAMES3 * 65536 ;
unsigned int  frame2 = *FRAMES2 * 256 ;
unsigned int  frame1 = *FRAMES1 ;
unsigned long frame  = frame1 + frame2 + frame3 ;
int  framy = sysword( FRAMES1 , FRAMES2 );
printf(" frames:\n%10u\n%10u\n%10u\n%10u since last NMI\n%10u\n",(long)frame1 ,(long)frame2 ,(long)frame3,(long)frame, framy );
printf(" frames:\n%10u\n%10u\n%10u\n%10u since last NMI\n%10u\n",frame1 ,frame2 ,frame3, frame, framy );
and sysword is just a 'word' :

Code: Select all

unsigned int sysword(unsigned char *a , unsigned char *b)
 {
  unsigned int sysword = *a  +256 * *b  ;
  return sysword ;
 }
You do not have the required permissions to view the files attached to this post.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: long for newbie's

Post by dom »

First of all, I think the best way to do this is the following:

Code: Select all

#include <stdio.h>

__at(23672) unsigned long FRAMES;

int main() {
        unsigned long clock = FRAMES & 0x00FFFFFF;

        printf("%lu\n",clock);
}
Since FRAMES is only 3 bytes we need to mask off the top 8 bits of the long.

You have these lines:

Code: Select all

unsigned int  frame2;
unsigned int  frame1;
unsigned long frame3;

printf(" frames:\n%10u\n%10u\n%10u\n%10u since last NMI\n%10u\n",(long)frame1 ,(long)frame2 ,(long)frame3,(long)frame, framy );

Your printf format is using %u which takes a 16 bit value, your call to printf() is either casting to a long or is passing a long. A long is a 32 bit value.

If we consider a simple view of the stack when you're calling printf():

Code: Select all

+0     frame1
+4     frame2
+8     frame3
+12    frame
+16    framy
At the start of printf() the argument pointer is set to +0, this argument pointer is incremented by the size of the variable that it prints.

So, it passes through the format string, comes across %u, prints an integer, increments the argument counter to +2, then hits the second %u, prints the integer and increments the argument pointer to +4, etc.

So you can see what's happening, the first %u prints the actual integer value, the second one prints 0/0xffff (since the int has been promoted to a long) and so on.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: long for newbie's

Post by dom »

The reason why you tend not to see this printf() issue when you use a compiler for a PC is probably two fold:

1. sizeof(int) == sizeof(long) for 32 bit OSs and for Windows x86_64
2.These functions are usually marked with __printflike which sanity checks the arguments vs the format string. You'll end up with warnings but it will "work"
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: long for newbie's

Post by cborn »

dom wrote: Fri Mar 12, 2021 9:50 am The reason why you tend not to see this printf() issue when you use a compiler for a PC is probably two fold:

1. sizeof(int) == sizeof(long) for 32 bit OSs and for Windows x86_64
2.These functions are usually marked with __printflike which sanity checks the arguments vs the format string. You'll end up with warnings but it will "work"
Hi, thanks for your long explanation.
I all ready did try gcc after zcc compiled without any error.
eg gcc remarks:
sysvar055d.c: In function ‘main’:
sysvar055d.c:534:8: warning: ‘return’ with a value, in function returning void
return 0;
^
So i removed that to much zero. I wont mind if zcc gives that message. is there a 'extra remarks' mode likw -Wall ??

About at(), i tried '__sfr __at() ' which is to much for this code.
There is a lot to get used to. in asm i have no problem with a mask so in C i should use it to. Thats very easy.
But i would not have had the notion to cut the result back to a 3 byte value. In basic a result is a kind of 'granted' while in 'c' its only 'accepted' , thats how it feels anyway.

so now i am going to be 'at()' it
cheers
Chris
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: long for newbie's

Post by cborn »

One off those other things is the variable types.
You print with %lu and i did have a look for all % commands but i did not find it.
i need my own pragma with 'try it instead off search' but that is the part that makes me run like a dog for its tail, again.
So, i will use L U as in %lu
cheers
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: long for newbie's

Post by cborn »

One more thing to learn is putting code outside the main and any routine.
In the clock example you put the _at() OUTSIDE. its at the same place as define and include.
zcc does not mention that, but thats is according the C error standards, another thing to learn
basic gives mostly error about the problem
C gives errors AFTER the problem which is the NEXT code part not to work properly.....
chris@cb:~/Desktop/try-C/c_in_zx/sysvars$ zcc +zx -vn sysvar055f.c -o sysvar055f -lndos -create-app
sysvar055f.c:378:5: warning: Implicit definition of function '__at' it will return an int. Prototype it explicitly if this is not what you want. [-Wimplicit-function-definition]
sysvar055f.c:378:13: fatal error: Expected ';'
Compilation aborted
technicly the error should be "function displacement" or something alike.
but i found it, by the simple example form Dom, so i hope i can compile it in my own memory now.
so i moved the at() to what i will call myself the "include zone"
yes, it works (beter)
Post Reply