Menu

#3730 va_arg (printf) fail completly on target Z80

closed-fixed
None
Z80
5
2024-04-29
2024-04-25
Bert Lange
No

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.

1 Attachments

Related

Bugs: #3674

Discussion

  • Bert Lange

    Bert Lange - 2024-04-25

    program

     
  • Janko Stamenović

    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:

     myprintf( "%x %x %x", (char)a, (char)b, (char)c);
    

    Regarding the other problems you have, no idea.

     

    Last edit: Janko Stamenović 2024-04-25
  • Bert Lange

    Bert Lange - 2024-04-26

    Ok, with

    myprintf( "%x %x %x", (char)a, (char)b, (char)c);
    

    variant 1 works.

    And also the workaround with

    c = va_arg( arg, unsigned);
    

    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

     
    • Philipp Klaus Krause

      Background: the char arguments get promoted to int. Keeping the char 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 be va_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.

       
      👍
      1
  • Philipp Klaus Krause

    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]

    • Janko Stamenović

      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 ?

      void print_hx16( unsigned u );
      void f(const char *fmt, ...) {
           print_hx16( (unsigned)fmt );
      }
      
      ;   ---------------------------------
      ; Function f
      ; ---------------------------------
      _f::
          ld  hl, #4
          add hl, sp
          ld  a, (hl)
          inc hl
          ld  h, (hl)
          ld  l, a
          jp  _print_hx16
      

      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
  • Philipp Klaus Krause

    Fixed in [r14829].

     

    Related

    Commit: [r14829]

  • Philipp Klaus Krause

    • status: open --> closed-fixed
    • assigned_to: Philipp Klaus Krause
    • Category: other --> Z80
     
  • Bert Lange

    Bert Lange - 2024-04-27

    Great, it works!
    Thank you!

     
  • Maarten Brock

    Maarten Brock - 2024-04-29
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -21,7 +21,7 @@
     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.
    +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
    
     

    Related

    Bugs: #3674


Log in to post a comment.