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.
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 »

Try

Code: Select all

unsigned char p[] = "Hello World!";
instead.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Btw, if you are including your .rodata in your linker script as:

Code: Select all

     *(.rodata)
Try replacing it with

Code: Select all

     *(.rodata*)
The reason is that if I objdump -h <object> on my gcc, I'd get something like:

Code: Select all

init.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000002cd  00000000  00000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000310  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000310  2**2
                  ALLOC
  3 .rodata       00000008  00000000  00000000  00000310  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .rodata.str1.1 0000001e  00000000  00000000  00000318  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .rodata.str1.32 00000072  00000000  00000000  00000340  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .note.GNU-stack 00000000  00000000  00000000  000003b2  2**0
                  CONTENTS, READONLY
  7 .comment      00000044  00000000  00000000  000003b2  2**0
                  CONTENTS, READONLY

See.. There's .rodata, but then there's .rodata.str1 and .rodata.str1.32 as well. All should go to the same place, in my case:

Code: Select all


OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

load_address = 0x100000; /* at 1M */

SECTIONS
{
    . = load_address;

    .text :
    {   
        *(.multiboot.header)    /* must be within 8k, so put first */

        *(.text)
        *(.rodata*)
    }

    .data : {
        data = .;
        *(.data)
    }

    .bss : {
        bss = .;
        *(.bss)
        *(COMMON)
    }

    _kernel_end = .;
}

of note: I use a special section in my boot.S to put multiboot header where it should be... I also use similar trick to put ctr0.S in the beginning of my OS programs since I don't have ELF loader in kernel yet, so they are just binaries for now.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Oh never mind, my memory failed, seems you already had that right...
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

I actually tried that right after my post.

If I do that my kernel triple faults:

Code: Select all

void main () {

	_clrscr (WINCOL);

	unsigned char p[]="HELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLD";

	__asm ("hlt");
}
Output from Bochs:

Code: Select all

00005146035e[CPU0 ] write_virtual_checks(): write beyond limit, r/w
00005146035e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00005146035e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00005146035i[CPU0 ] protected mode
00005146035i[CPU0 ] CS.d_b = 32 bit
00005146035i[CPU0 ] SS.d_b = 32 bit
00005146035i[CPU0 ] | EAX=0000000e  EBX=00007a00  ECX=0000000e  EDX=000b8eff
00005146035i[CPU0 ] | ESP=0008ffb0  EBP=0008fff8  ESI=00001c20  EDI=0008ffb0
00005146035i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00005146035i[CPU0 ] | SEG selector     base    limit G D
00005146035i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00005146035i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00005146035i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005146035i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005146035i[CPU0 ] |  ES:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00005146035i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00005146035i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00005146035i[CPU0 ] | EIP=0000110d (0000110d)
00005146035i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00005146035i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00005146035i[CPU0 ] >> rep movsd dword ptr es:[edi], dword ptr ds:[esi] : F3A5
00005146035e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
I went back to my code and insured it.. keeping it as unsigned char*
works while unsigned char p[] causes a triple fault.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

You should consider the possibility that if you are using DJGPP, it is somewhat of a hack to get GCC compile to MSDOS, and even if it wasn't, it's not really very actively maintained so it's old, possibly doing things that newer GCCs would not do.

If you pick'ed a more recent GCC, you could expect it to not only generate better code, but also avoid problem when compiling a kernel, because GCC is what Linux gets compiled with, and if Linux has problems with some version of GCC, that version won't live very long these days. :)

I think you should at least try to compile your kernel with a recent GCC. If you have access to Linux (on i386) you can use the native GCC there just fine. If not, there's supposedly help how to make a cross-compiler out of Cygwin (don't know where it is, since I compile my OS in Linux).

If you get the same result with a more recent gcc which is known to be able to create clean binaries, then you know it's your code that's faulty, which makes life somewhat easier...
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

neon wrote: I went back to my code and insured it.. keeping it as unsigned char*
works while unsigned char p[] causes a triple fault.
Oh ok. It'll tell you why. When you write

Code: Select all

     unsigned char p[] = "foobar";
Your compiler will (every time you enter the function) allocate p[] from the stack, and initialize it with the contents of "foobar".

If you use a pointer, it'll just allocate a pointer instead, and make that point to the string constant.

Why this fails? It could be your compiler inlining calls to builtins like alloca or strlen/strcpy or whatever, which don't work in your kernel environment. It could be that your compiler references the string using a method that doesn't work in your kernel (segment registers? you should try setting valid ES(=DS=SS) since you still don't seem to do that) or it could be any number of other reasons...
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Code: Select all

> rep movsd dword ptr es:[edi], dword ptr ds:[esi] : F3A5 
Yeah well, that looks like ES-segment access to me, which I'd say won't work if ES is 0 (which is special case, ignore whatever else Bochs says about it, since 0 is nil is null is will-fault-on-use).
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
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 »

I upgraded GCC on my DJGPP distro recently, now I'm up-to-date.

DJGPP is very useful for Windows users, Cygwin can be a real pain sometimes (the only thing I use it for is it's dd command :D)
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 »

Question for neon: have you initialised an IDT and a GDT yet? If not, do so and see if that fixes your problem.

Either way CS=DS=ES=SS... you can fix that in your bootloader:

Code: Select all

mov ds,cs
mov es,cs
mov ss,cs
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

pcmattman wrote:

Code: Select all

mov ds,cs
mov es,cs
mov ss,cs
That will not work. For one, CS needs a code segment, DS/ES/SS need a data segment....

Anyway, the point is, CS, DS and SS look like they should, so just initialize ES where DS is initialized. This is adds exactly one line of code.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Setting ES=DS resolved the triple faults.

It still seems to only print the string after assigning it though.
ie:

Code: Select all

unsigned char p[]="HELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLD";

_printf (p);
prints null, while:

Code: Select all

unsigned char p[]="HELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLDHELLO WORLD";

int i=0;
for (i=0; i<10; i++)
     p[i]='3';


_printf (p);
...prints the character '3'.

I will try this with a newer version of GCC, and see what happens..
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

I just installed gcc 4.1.0 and ld 2. 17, however I had the same problem..

After adding the -i option (My older LD didnt support it):

Code: Select all

gcc -ffreestanding -nostdlib -nostartfiles -c -o Main.o Main.c
ld -i Link.ld -o KERNEL.o Stage2.o Main.o
It seems to be working fine when I add the -i option, but it doesnt
work without it.

Its working though! (Finally!) :D

Thanks to everyone SO much! Serously--this is one of the
issues that stopped my OS development before. I would have
never got it working if it wasnt for this great community!

Thanks again!! :D

btw, I thought the -i option is just for incremental compiliation.
(Decreasing the size of the image)
Why would it only work with it, but not work without it..?
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Code: Select all

ld -T Link.ld -o KERNEL.o Stage2.o Main.o 
Would seem like the correct command line to me.

If I was you, I'd test if -T works, and if it does, use that instead, because the reason -i works might be some strange side-effect of the incremental linking, and if I was you, I'd rather not rely on it.

-T will replace the script with the one you provide.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Oh, and don't EVER EVER EVER "think" anything about command line arguments. Always read the manual, especially if the tool originated in Unix. Even if you "think" you remember what some options to, you still better check them from the manual until you've used them enough to remember them by heart (as in, you could write a manual entry out of your head that gives the same information as the original).

My ld says following about incremental link:

Code: Select all

       -i  Perform an incremental link (same as option -r).
and looking at -r

Code: Select all

       -r
       --relocatable
           Generate relocatable output---i.e., generate an output file that can in turn serve as  input  to  ld.   This  is
           often  called partial linking.  As a side effect, in environments that support standard Unix magic numbers, this
           option also sets the output file's magic number to "OMAGIC".  If this option is not specified, an absolute  file
           is  produced.   When  linking C++ programs, this option will not resolve references to constructors; to do that,
           use -Ur.

           When an input file does not have the same format as the output file, partial linking is only supported  if  that
           input  file does not contain any relocations.  Different output formats can have further restrictions; for exam-
           ple some "a.out"-based formats do not support partial linking with input files in other formats at all.

           This option does the same thing as -i.
Unless you understand why this makes your kernel work, you are relying on some "magic" and you should never do that, because it can break at any time, leaving you with no clue whatsoever. :)
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

You made a very good point about using the option, and how it could
break at any moment.

Adding -T to my linker causes objcopy to generate an error
("File format not recognized'):

Code: Select all

ld -T Link.ld -o KERNEL.o Main.o
objcopy -R .note -R .comment -S -O binary KERNEL.o KERNEL.bin
objcopy.exe: KERNEL.o: File format not recognized
I am currently doing research to see if I can find anything.

I suspect its the output from my linker script (Though I dont see how.
The linker script is set for binary output, and my objcopy supports
binary files):

Code: Select all

ENTRY("0x00000000")
OUTPUT_FORMAT("binary") 

SECTIONS 
{ 
    .text 0x1000 : 
    { 
        code = .; _code = .; __code = .; 
        *(.text*)
    } 
    .data : 
    { 
        data = .; _data = .; __data = .; 
        *(.data*) 
    } 
    .rodata :
    {
	rodata = .; _rodata = .; __rodata = .;
        *(.rodata*)
    }
    .bss : 
    { 
        bss = .; _bss = .; __bss = .; 
        *(.bss*) 
    } 

    end = .; _end = .; __end = .; 
}
Last edited by neon on Sat Mar 24, 2007 10:35 pm, edited 1 time in total.
Post Reply