Text output; pointer problems

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Text output; pointer problems

Post by neon »

Hello everyone,

In addition to my previous problem (Posted in my other post),
I am also having pointer issues with C in my kernel.

I am currently using DJGPP.

I have a simple _putch() routine (Puts a character on screen),
and it works just fine.

I attempted to write a version of _printf(). At the moment, it litterally
does nothing:

Code: Select all

void _printf (const char* format, ...) {

}
Calling this function from main() causes my kernel to triple fault.

I know the most common solution to this problem is including .rodata
section in my linker script, but I have that..

Here is my linker script:

Code: Select all

ENTRY(__Stage2)
OUTPUT_FORMAT("binary") 
SECTIONS 
{ 
    .text 0x1000 : 
    { 
        code = .; _code = .; __code = .; 
        *(.text) 
        *(.rodata*)
        . = ALIGN(4096); 
    } 

    .data : 
    { 
        data = .; _data = .; __data = .; 
        *(.data) 
        . = ALIGN(4096); 
    } 

    .bss : 
    { 
        bss = .; _bss = .; __bss = .; 
        *(.bss) 
        . = ALIGN(4096); 
    } 

    end = .; _end = .; __end = .; 
}
Thanks for any help!

(Im just trying to get text on the screen!!)
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Adding -fwritable-strings to gcc seems to have fixed the triple fault, but
nothing is being printed...

Code: Select all

void main () {

	_clrscr (WINCOL);
	_putch ('M');         // works

	_printf ("H");      // Nothing is printed
	__asm ("hlt");
}

void _printf (const char* format, ...) {

	_putch (*format);
}
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Ummm... correct me if I'm wrong but isn't .rodata meant to be in either the BSS or DATA sections?

Also I'd suggest that you don't start with a 'printf' until you have a working va_list (or some other form of retrieving an unknown number of arguments).

My text output routines started with 'kputc' (this was way back before I even thought about what I have now :D), then 'kputs', then after a lot of time, 'printf' (I never got around to implementing kprintf, probably because printf's character output routine is kputc - so there's no real difference between the two).
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

<standard_reply>Try using Bochs' Debugger</standard_reply>

@pcmattman
.rodata is in the .text section because its read-only. putting it in .data is ok but less secure, putting it in .bss is an invitation for confusion and related problems.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

Combuster wrote:@pcmattman
.rodata is in the .text section because its read-only. putting it in .data is ok but less secure, putting it in .bss is an invitation for confusion and related problems.
putting it in .bss is kinda dumb because it is unintialised data and a string is always initialised. ok, now for the .text section. if i put machine code in a read only string. putting the rodata in a text section means that i can execute my machine code because it is located in a code segment. if i however put the string in the .data section and seperate the data section in a read-only and read/write part (on page alignment) i can protect the string by for instance the NX bit rendering the machine code useless.

conclusion imho .data is the only correct location for .rodata.
Author of COBOS
urxae
Member
Member
Posts: 149
Joined: Sun Jul 30, 2006 8:16 am
Location: The Netherlands

Post by urxae »

This may be a stupid question, but why not put .rodata in, you know, .rodata?
That way you can mark it as non-executable and read-only.

That's what I do, anyway...
User avatar
salil_bhagurkar
Member
Member
Posts: 261
Joined: Mon Feb 19, 2007 10:40 am
Location: India

Post by salil_bhagurkar »

Try removing the '...' from the _printf function. When you are not using va_list then you should try the following function:

Code: Select all

void _printf(const char *format)
{
        _putch(*format);
}
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

I put *(.rodata*) in the .data section, but it still prints nothng.

I also put *(.rodata*) in its own section, still nothing.

Here is my _printf that I used:

Code: Select all

void _printf (const char* format) {
	_putch (*format);
}
My new linker script (with .rodata section):

Code: Select all

ENTRY(__Stage2)
OUTPUT_FORMAT("binary") 
SECTIONS 
{ 
    .text 0x1000 : 
    { 
        code = .; _code = .; __code = .; 
        *(.text) 

        . = ALIGN(4096); 
    } 
    .data : 
    { 
        data = .; _data = .; __data = .; 
        *(.data) 
        . = ALIGN(4096); 
    } 
    .rodata :
    {
		rodata = .; _rodata = .; __rodata = .;
        *(.rodata*)
        . = ALIGN(4096);
    }
    .bss : 
    { 
        bss = .; _bss = .; __bss = .; 
        *(.bss) 
        . = ALIGN(4096); 
    } 

    end = .; _end = .; __end = .; 
}
Any more suggestions?

Im going to run it through the debugger and see if I can find anything...
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

Man all those underscores are ugly.. :?
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Im officialy confused o.0:

My linker is loading my kernel from address 0x18f8, but it is supposed
to be 0x1000. (Please see my other post for the warning from the linker
I get...)

I used objdump to disassemble it:

Code: Select all

Disassembly of section .text:


//My linker loads kernel at 0x18f8--beginning here, but I cant
// get objdump to disassemble it..
000018f8 <_main-0x8>:
        ...

00001900 <_main>:
    1900:       55                      push   %ebp
    1901:       89 e5                   mov    %esp,%ebp
    1903:       83 ec 08                sub    $0x8,%esp
    1906:       83 e4 f0                and    $0xfffffff0,%esp
    1909:       b8 00 00 00 00          mov    $0x0,%eax
    190e:       29 c4                   sub    %eax,%esp
    1910:       83 ec 0c                sub    $0xc,%esp
    1913:       6a 1f                   push   $0x1f
    1915:       e8 22 00 00 00          call   193c <__clrscr>
    191a:       83 c4 10                add    $0x10,%esp
    191d:       83 ec 0c                sub    $0xc,%esp


// Here we push address 0x2008 on the stack, containing our string
// we want _printf to output. We call printf...
    1920:       68 08 20 00 00          push   $0x2008
    1925:       e8 0e 01 00 00          call   1a38 <__printf>

    192a:       83 c4 10                add    $0x10,%esp
    192d:       f4                      hlt
    192e:       c9                      leave
    192f:       c3                      ret
Printf:

Code: Select all

00001a38 <__printf>:
    1a38:       55                      push   %ebp
    1a39:       89 e5                   mov    %esp,%ebp
    1a3b:       83 ec 08                sub    $0x8,%esp
    1a3e:       83 ec 0c                sub    $0xc,%esp
    1a41:       8b 45 08                mov    0x8(%ebp),%eax
    1a44:       0f be 00                movsbl (%eax),%eax
    1a47:       50                      push   %eax
    1a48:       e8 49 ff ff ff          call   1996 <__putch>
    1a4d:       83 c4 10                add    $0x10,%esp
    1a50:       c9                      leave
    1a51:       c3                      ret
The important lines from main():

Code: Select all


// Here we push address 0x2008 on the stack, containing our string
// we want _printf to output. We call printf...
    1920:       68 08 20 00 00          push   $0x2008
    1925:       e8 0e 01 00 00          call   1a38 <__printf>
Notice we push address 0x2008 on the stack. What is at this
address...? :

Code: Select all

Disassembly of section .data:

00002000 <djgpp_first_ctor>:
    2000:       00 00                   add    %al,(%eax)
        ...

00002004 <__yPos>:
    2004:       00 00                   add    %al,(%eax)
        ...

00002008 <LC0>:
    2008:       48                      dec    %eax   <<<<< My "H"
    2009:       00 00                   add    %al,(%eax)
The value 0x48! Which translates to the ASCII character H!
(The character I am trying to print as a string)

...Yet _printf still prints null...

Any more ideas..?
Last edited by neon on Mon Mar 19, 2007 10:14 pm, edited 1 time in total.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Just want to add:

Code: Select all

void _printf (const char* format) {

	_putch (*format);	//prints nothing
	//_putch ('A');	// works
}
At first I was suspecting a stack problem, but nonpointer
parameters work just fine..
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Have you tried it without the 'const'? The parameters don't have to be constant, it just helps you make sure that you don't overwrite them later. Try removing the 'const' and see if it fixes the problem.
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

can we see the code for putch because if you print it in the same foreground as background color you will not see it, though it has been printed. :wink:
Author of COBOS
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

I took the const out, but still doesnt work (Same problem--prints nothing)

Heres my _putch:

Code: Select all

#define		VIDMEM	0xB8000	// video memory
#define		COLS	80	// width and height
#define		LINES	24
#define		ATTRIB      0x1F
#define		WINCOL	0x1F	// Window color

static	int	_xPos=0;	// current position
static	int	_yPos=0;

void _putch (int c) {

	unsigned char* vmem = (unsigned char*)VIDMEM;

	//watch for newline
	if (c=='\n' || c=='\r') {

		_xPos=0;
		_yPos++;
		if (_yPos>LINES)
			_yPos=0;

		return;
	}

	// write the character
	*(vmem + (_xPos + _yPos * COLS) *2) = c & 0xFF;
	*(vmem + (_xPos + _yPos * COLS) *2+1) = ATTRIB;

	// watch for end of line
	if (_xPos++ >COLS)
		_putch ('\n');
}
All of the characters use 0x1f for its attribute (Which is yellow text on
blue background)

(I was really thinking taking const out would fix it...)

Any more suggestions,,,>

I confused at what the prolem could be... :(
User avatar
Alboin
Member
Member
Posts: 1466
Joined: Thu Jan 04, 2007 3:29 pm
Location: Noricum and Pannonia

Post by Alboin »

Instead of:

Code: Select all

   *(vmem + (_xPos + _yPos * COLS) *2) = c & 0xFF;
   *(vmem + (_xPos + _yPos * COLS) *2+1) = ATTRIB; 
Try:

Code: Select all

   vmem[(_xPos + _yPos * COLS) *2)] = c & 0xFF;
   vmem[(_xPos + _yPos * COLS) *2+1)] = ATTRIB; 
I think it's equivalent, actually...but, why not try it? It's what I use in my kernel, and it works nicely...

Edit: And why is c an int? Just use a char, and you can save yourself the trouble of writing

Code: Select all

c & 0xFF
C8H10N4O2 | #446691 | Trust the nodes.
Post Reply