Page 1 of 1

problem with printf function

Posted: Tue Sep 10, 2002 11:00 pm
by Dabbo
Hi,

Sorry for so newbie question - but it`s very hard to me understand whats going wrong. Here comes my problem:

Currently I`m working on printf procedure, and I can`t figure why (and when) I use variable amount of arguments (in procedure), following fp procedure simply print wrong value, here goes my code:

#include <fp.h>
int main {
[...]
fp("Example: ",0x4321); // simply prints wrong number
[...]
}

//======================= file gp.h
#include <stdarg.h> // comes from djgpp source tree

void fp (const char * st, ...) {
  va_list arg;
  int  a;
  va_start (arg, st);
[...]
  a= va_arg(arg, int);
  printf(a); // prints `a` number direct to screen
[...]
  va_end(arg);
};
//=======================

here goes my command line switches for gcc:

gcc -c -W -I../include -fomit-frame-pointer

here goes my gdt:

dummy_descr: make_descript 0, 0, 0, 0
code32_descr: make_descript 0x0, 0xffffff, D_present | D_mem | D_code_ExR, D_word | D_page_gr
crt_descr: make_descript 0xb8000, 4096, D_present | D_mem | D_data_RW, 0
stack32_descr: make_descript 0x5000, 0x1fff, D_present | D_mem | D_data_RW, 0
flat32_descr: make_descript 0x0, 0xffffff, D_present | D_mem | D_data_RW, D_page_gr

My kernel starts at 0x100000. I suppose it could stack problem (?) - but I`m not sure.

Thanks for any ideas/answers,
Dab

RE:problem with printf function

Posted: Tue Sep 10, 2002 11:00 pm
by carbonBased
There's a few problems here:

1. valist, etc. may not be portable/useable in osDev.
2. the use of printf is _definitly_ not portable/useable in osDev.
3. You're sending an integer to printf as the first parameter, which should be a char *

Why are you rewritting printf using printf, anyway?  That seems a little counter productive.

If you want a base printf, check out the multiboot specs.  They include a simply printf implementation suitable for osDev.  My OS uses a slightly altered version, which supports "output lengths" (ie, like %8x) (www.neuraldk.org/osDev.html, if I remember right)

Jeff

RE:problem with printf function

Posted: Thu Sep 12, 2002 11:00 pm
by anton
I don't see why valist, etc are not portable: valist , etc. are just tricky macros that use stack.

Anton

RE:problem with printf function

Posted: Thu Sep 12, 2002 11:00 pm
by carbonBased
They assume an expand-up stack, that's all.
I just don't trust any code written for and in a system other than my own.  Perhaps a bit paranoid.

It's not difficult to write a printf without using valist, either:

int printf (const char *format, ...) {
  char **arg = (char **) &format;

  arg++;
  // arg now contains the first variable length argument
}

Jeff

RE:problem with printf function

Posted: Thu Sep 12, 2002 11:00 pm
by Anon
how would you actually write an ASM printf but use it in C?  I have no asm coding experience and this would help me out a lot.  Thank you

RE:problem with printf function

Posted: Thu Sep 12, 2002 11:00 pm
by Tim Robinson
They assume an expand *down* stack. At least, the ones I've seen do.

And that's the point: you can't assume anything. You've got to write the libc code according to how *your* system works.

For an expand-down stack (i.e. the norm), that example would be:

int printf(const char *format, ...)
{
    void **args = (void**) &format;
    args--;

    /* args now points to the first argument after format */
}

RE:problem with printf function

Posted: Fri Sep 13, 2002 11:00 pm
by carbonBased
Well, yeah, but according to Intel it's "expand up"... their definitions are counter-intuitive.  In other words, esp decrements on each push, right?  Those are the ones I've seen (well, all of two, so... :)

Jeff

RE:problem with printf function

Posted: Sat Sep 14, 2002 11:00 pm
by anton
Stack grows when you do a push, right?
So,
1)if the esp decrements on each push--expand down
2)if the esp increments on each push--expand up;

intel has a expand down stack!!!
Anton

RE:problem with printf function

Posted: Sat Sep 14, 2002 11:00 pm
by carbonBased
IA32 systems can have _either_ expand up or expand down... it's defined in the stack descriptor (the E bit)

And according to "Protected Mode Software Architecture" (AND the Intel manuals, I might add), on an expand _up_ stack, esp decrements!

I'm well aware of how contradictory this is, but according to Intel:
esp _increments_ on each push--expand down
esp _decrements_ on each push--expand up

Jeff

RE:problem with printf function

Posted: Sun Sep 15, 2002 11:00 pm
by Dabbo
Hello,

It was only simple example to show my problem - that`s why I write hipotetic fp procedure,
anyway:

First, I found following solution:

void printf (char * st, ...) {
  ptr arg= (ptr)(&arg+3); // ptr = char *
[...]

[...]
a=peekl_sel( (ptr)arg, 0x18); arg+=4; // 0x18 is stack selector
[...]

It worked fine for me, but following piece of code seems to be more clearier ...

char **arg = (char **) &format;

Thanks for all comments,
Dabbo

RE:problem with printf function

Posted: Sun Sep 15, 2002 11:00 pm
by Tim Robinson
Since you're using C, I'd recommend that you make the stack and data segments the same (or at least give them the same base address). Otherwise, this code won't work:

/* in the .data section */
char a_global[10];

int main(void)
{
    /* on the stack */
    char a_local[10];

    /* writes to DS:a_global */
    strcpy(a_global, "hello");

    /* writes to DS:ptr, where ptr=ebp+4 -- WRONG */
    /* should write to SS:ptr, but strcpy doesn't know that */
    strcpy(a_local, "world");

    return 0;
}

RE:problem with printf function

Posted: Mon Sep 16, 2002 11:00 pm
by Dabbo
Yes u are right. So, if ss has the same selector as ds then we have:

Adventages:
o simple and direct access to all arguments on stack;

Disadventages:
o data segment have to share space with stack - in my opinion it could be not secure (for example badly write recursive procedure, buffer overflows etc);
o it`s hard to control stack grows (stack can "grow" to 0 address and overwrite important data ...);

Am I right ?

ps.
how it is in linux ?

Dabbo

RE:problem with printf function

Posted: Mon Sep 16, 2002 11:00 pm
by Schol-R-LEA
As I understand it, Linux uses a flat memory scheme. That is, for each process, all the selectors are logically zero-based, and treated as a single memory space within the process (Linux uses paging, which remaps the logical memory to physical memory actually used, so each process thinks it has the entire address space available).

HTH. CCW.

RE:problem with printf function

Posted: Mon Sep 16, 2002 11:00 pm
by carbonBased
As Schol-R-Lea pointed out, Linux does indeed use a flat model, where all selectors start at 0, and extend the full 4GB.  This is the way most modern OSs work (it's simple, and effective, and interfaces well with most programming languages, noteably C, of course).

Some things to note, though; a badly written program is gonna crash.  You can't save a badly written program, that's not the job of the OS.  The OS simply has to make sure that when that program crashes, it doesn't take down anything else with it.

Because most modern OSs use paging, no single process has access to any other processes memory space, and so the only memory a stray task is going to screw up is its own - no problem.

Lastly, if you set up your paging correctly a stack will not be able to grow to 0x0.  For example, your stack can be positioned at the top of memory (0xffffffff), and be, say, 16kb.  So, at 4GB - 16kb, place a non-present page in the page directory.  In this case, if the program tries to grow past its allocated stack, it'll cause a stack fault (and if handled incorrectly, will also case a double, and then a triple fault, but that's another story altogether, which has been talked about a few times on this list).

Essentially, all I'm saying is, the two disadvantages you've listed aren't critical.  Don't worry 'bout 'em.  Like I said, a badly written program is going to crash... you can't change that.

Jeff

RE:problem with printf function

Posted: Tue Sep 17, 2002 11:00 pm
by Dabbo
All is clear,
thx for all
Dab