Re: why this program is not crashing

From: kingzog (kingzog_1_at_lycos.com)
Date: 02/14/05


Date: 14 Feb 2005 06:38:56 -0800

Jack Klein wrote:
> On 11 Feb 2005 05:31:01 -0800, "kingzog" <kingzog_1@lycos.com> wrote
>
> > Is there a machine that needs this? Surely if they have the same
size
> > and representation it whould work without the cast. I've certainly
> > never needed to cast char * to void * in a printf like this, and
I've
> > used some really wierd C compilers, e.g. on DSPs.
>
> That fact that it works on the compilers where you have tested it, or
> 99% of all compilers, or even 101% of all compilers does not prove
> anything.
>

Yes but if all the compilers I need to support don't need it, my code
doesn't need it either. In fact most embedded C code is only designed
to support one compiler and one architecture and has far more serious
portability issues than this - e.g. assumptions about endianess or
stucture packing or gobs of inline assembler and hardware access.

>
> So this is a QOI issue, not a standard one.

??

>
>
> > I'd bet that the addresses passed to printf will be on the stack
too.
> > Even on a 64 bit machine, where buf1[5] might fit in a register,
the C
> > compiler would need to stack it before the call to printf.
>
> What "stack"? On some platforms, the four arguments in that printf()
> call would all be passed in registers. And the return address in a
> dedicated register of its own. No "stack" need apply.

Every platform I've seen uses the stack for printf, because it's the
most efficient way to implement va_next - va_start can create a hidden
pointer to the args on the stack, and va_next can do *hidden_ptr++ and
some masking.

If the args were in registers, you'd need either a need a wierd
addressing mode like this

mov Rdest, Registers[Rcount] ; mov the register number Rcount into
Rdest

I've never seen a architectures that provides this addressing mode. As
a HW guy it looks hard to implement. You could do two loads from the
register file, one to read Rcount and one to read Registers[Rcount], or
you could have add _lots_ of read ports to the register file.

On a normal chip, the C compiler could use self modifying code to
synthesise it -

mov Rtmp, Rcount
shift Rtmp, #xx ; shift Rcount to line up with the register field
                  ; in the instruction
or Rtmp, [label]
label:
mov Rdest, R0 ; R0 is a constant field in the instruction
                 ; which the previous instruction overwrites

But self modifying code is slow because it flushes pipelines, and
causes problems if you have a read only code page. It's also worth
pointing out that both of these solutions will break if you try to pass
more arguments to printf than you have usuable argument registers.
E.g. consider a printf on a Risc chip which allows 4 registers to pass
arguments. One call to printf with 5 arguments would require a second
copy of the function with the stack based calling convention.

So even on Risc machines where the normal calling convention is to pass
args in registers, variadic functions still pass the args to printf on
the stack. It's probably fast too, because the top of the stack is
pretty much guaranteed to be in a cache or write buffer when the
variadic function calls va_next. Then again, if you want speed, you'd
make the function non variadic and declare it INLINE with inline
#defined to be something appropriate for the compiler
(http://www.greenend.org.uk/rjk/2003/03/inline.html)

>
> --
> Jack Klein
> Home: http://JK-Technology.Com
> FAQs for
> comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
> comp.lang.c++ http://www.parashift.com/c++-faq-lite/
> alt.comp.lang.learn.c-c++
> http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html



Relevant Pages

  • Re: [OT] PostLisp, a language experiment
    ... >> that a C compiler generates code to arrange the parameters where it ... > value from the user stack. ... > can be simply passed in registers. ... common for the top stack item to reside in a register, ...
    (comp.lang.lisp)
  • Re: next mystery: 32 vs 64 bits...
    ... single pass compiler to use ret n for loops and stackframe. ... namely, they are no longer regarded as 'registers', even for the stack. ... With the dependence of the x86 instruction set on EAX, ...
    (alt.lang.asm)
  • Re: Kernel Calling Conventions
    ... The C calling convention is touted as being more convenient, ... passing arguments within registers. ... calling convention is to use registers and not the stack. ... over the DJGPP GCC based compiler, is due to the fact that the OW ...
    (comp.lang.asm.x86)
  • Re: Kernel Calling Conventions
    ... The C calling convention is touted as being more convenient, ... passing arguments within registers. ... stack as opposed to passing them via registers? ... by the C compiler or tell the C compiler to "reoptimize" your assembly code. ...
    (comp.lang.asm.x86)
  • Re: puzzle in C
    ... printf() the format string "%d, a+b" but you didn't give it a value to ... Since your format string includes %d the printffunction ... Arguments to functions are conventionally passed on the stack. ... differently depending on your compiler, ...
    (comp.lang.c)