Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't my char* passing correctly?

Tags:

c

Problem statement (using a contrived example):

Working as expected ('b' is printed to screen):

void Foo(const char* bar);

void main()
{
    const char bar[4] = "bar";
    Foo(bar);
}

void Foo(const char* bar)
{
    // Pointer to first text cell of video memory
    char* memory = (char*) 0xb8000;
    *memory = bar[0];
}

Not working as expected (\0 is printed to screen):

void Foo(const char* bar);

void main()
{
    Foo("bar");
}

void Foo(const char* bar)
{
    // Pointer to first text cell of video memory
    char* memory = (char*) 0xb8000;
    *memory = bar[0];
}

In other words, if I pass the const char* directly, it doesn't pass correctly. The const char* I get in Foo points to zeroed out memory somehow. What am I doing wrong?

Background info (as requested):

I am developing an operating system for fun, using a guide I found here. The guide generally assumes you are on a unix-based machine, but I'm developing on a PC, so I'm using MinGW so that I have access to gcc, ld, etc. In the guide, I am currently on page 54, where you have just bootstrapped your custom kernel. Rather than simply displaying an 'X' as the guide teaches, I decided to use my existing knowledge of C/C++ to attempt to write my own rudimentary print string function. The function is supposed to take a const char* and write it, char by char, into video memory. Three files are currently involved in the project:

  • The boot sector - compiled through NASM to a .bin file
  • The kernel entry routine - compiled without linking through NASM to a .o, linked against the kernel
  • The kernel - compiled through gcc, linked along with the kernel entry routine through the ld command, which produces a .bin which is appended to the .bin file produced by the boot sector

Once the combined .bin file is generated, I am converting it to .VDI (VirtualBox Disk Image) and running it in a VM I have set up.

Additional info:

I just noticed that when VirtualBox is converting the .bin file to .vdi, it is reporting different sizes for the two examples. I had a hunch that maybe the string was getting omitted entirely from the compiled product. Sure enough, when I look at .bin for the first example in a hex editor, I can find the text "bar", but I can't when I look at a hex dump for the .bin of the second example.

This leads me to believe that the compilation process I'm using has a flaw in it somewhere. Here are the commands I'm using:

nasm boot_sector.asm -f bin -o boot_sector.bin
nasm kernel_entry.asm -f elf -o kernel_entry.o
gcc -ffreestanding -c kernel.c -o kernel.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o
objcopy -O binary -j .text kernel.tmp kernel.bin
copy /b boot_sector.bin+kernel.bin os_image.bin

os_image.bin is what is converted to the .vdi file which is used in the vm.

like image 612
Brian Gradin Avatar asked Oct 12 '14 07:10

Brian Gradin


People also ask

What does char * mean in C?

In C, char* means a pointer to a character. Strings are an array of characters eliminated by the null character in C.

What does char * p mean in C?

In C programming language, *p represents the value stored in a pointer and p represents the address of the value, is referred as a pointer. const char* and char const* says that the pointer can point to a constant char and value of char pointed by this pointer cannot be changed.

Can a char * be passed as const * argument?

In general, you can pass a char * into something that expects a const char * without an explicit cast because that's a safe thing to do (give something modifiable to something that doesn't intend to modify it), but you can't pass a const char * into something expecting a char * (without an explicit cast) because that's ...

What does the * after char mean C?

The asterisk in 'char *c' means that it is a pointer to a char. The pointer is initialised to point to the start address of the array test[]. ( this is the same as &test[0] )


1 Answers

With your first example, the compiler will (or at least, can) put the data to initialize the automatic array right in the code (.text section - moves with immediate values are used when I try this out).

With your second example, the string literal is put in the .rodata section, and the code will contain a reference to that section.

Your objcopy command only copies the .text section, so the string will be missing in the final binary. You should add the .rodata section, or remove the -j .text entirely.

like image 147
Mat Avatar answered Sep 29 '22 21:09

Mat