problem with printf function
-
Dabbo
problem with printf function
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
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
-
carbonBased
RE:problem with printf function
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
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
-
anton
RE:problem with printf function
I don't see why valist, etc are not portable: valist , etc. are just tricky macros that use stack.
Anton
Anton
-
carbonBased
RE:problem with printf function
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
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
-
Anon
RE:problem with printf function
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
-
Tim Robinson
RE:problem with printf function
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 */
}
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 */
}
-
carbonBased
RE:problem with printf function
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
Jeff
-
anton
RE:problem with printf function
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
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
-
carbonBased
RE:problem with printf function
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
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
-
Dabbo
RE:problem with printf function
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
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
-
Tim Robinson
RE:problem with printf function
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;
}
/* 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;
}
-
Dabbo
RE:problem with printf function
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
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
-
Schol-R-LEA
RE:problem with printf function
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.
HTH. CCW.
-
carbonBased
RE:problem with printf function
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
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