Hi folks,
here is (a reduced) sample code to (hopefully) reproduce the problem:
int main()
{
char a, b, c;
myprintf( "31 32 33 (expected)\n");
a = '1'; b = '2'; c = '3';
myprintf( "%x %x %x\n", a, b, c);
return 0;
}
In myprintf I just use va_arg to read the parameters (complete code as attachment).
My first compile command:
sdcc -mz80 --nostdlib -Wall -S main.c -o main.asm
The result is "31 00 32" and I got trouble with my host system, because it need the IX register is used by system (in interrupts).
The error reported on [#3674] looks similar.
My second compile attempt is with the '--fomit-frame-pointer' option:
sdcc -mz80 --fomit-frame-pointer --nostdlib -Wall -S main.c -o main.asm
Here it seem that the parameters show to a complete other location, but not to the format string.
I have attached some screenshots and the program.
second attempt
program
When I use
c = va_arg( arg, unsigned );
I do get 31 32 33 (replacing putchar with the one that works on my platform, of course).Also see this discussion here:
https://sourceforge.net/p/sdcc/mailman/sdcc-user/thread/208722254.20060614183338%40ltec.ch/
if you do want to use
va_arg( arg, char )
there you have to be explicit in the function call, like this:Regarding the other problems you have, no idea.
Last edit: Janko Stamenović 2024-04-25
Ok, with
variant 1 works.
And also the workaround with
does help.
But my second compile with the compile option '--fomit-frame-pointer' is still completly garbled up.
Can anyone give a hint in which sdcc source files a can search for the problem?
thanks & regards,
Bert
Background: the
char
arguments get promoted toint
. Keeping thechar
to save memory on the stack is an SDCC extension for some ports, only enabled when an explicit cast is used, and the SDCC C dialect is used (--std-sdccXX
(default), not--std-cXX
).So that
va_arg(arg, unsigned)
should probably beva_arg(arg, int)
and is not a workaround, but what the C standard requires. I'll have a look at the--fomit-frame-pointer
issue later today, to see if I can reproduce it.In [r14828], I added a regression test for this bug. When compiled with --fomit-frame-pointer, it indeed fails for the test-ucz80 target.
Related
Commit: [r14828]
Maybe that calculation where the parameters on the stack start is off-by-two when the
function f( fmt, ... )
is generated with --fomit-frame-pointer ?Maybe that 4 should be 2 to just skip over the return address? What I get is exactly the bytes with values 0x31 and 0x32 (the parameters passed as (char)a, (char)b) instead of the address where fmt is.
Edit:
I think I remember that in some implementations there's also the total number of the parameters passed on the stack as the additional parameter which then has to be skipped. I don't know if such is needed in this implementation, but if it is, then the call should be fixed to push that too, and the offsets are then OK.
Last edit: Janko Stamenović 2024-04-26
Fixed in [r14829].
Related
Commit: [r14829]
Great, it works!
Thank you!
Diff:
Related
Bugs: #3674