coperating-systemprotected-mode

Function pointer is 0 after cast


I am trying to develop my own OS. While setting up the IDT, I want to get address of the ISR0 function using &isr0 like this:

//The example function
void isr0() {
    volatile uint8_t* ptr1 = (uint8_t*)(0xB8000);
    ptr1[0] = 'A';
}
void main(){
    int ptr = (int)&isr0;
    volatile uint8_t* ptr1 = (uint8_t*)0xB8000;
    int offset2 = 40;
    int value = (int)ptr;
    ptr1[0 + offset2] = 48 + (value/100000) % 10;
    ptr1[2 + offset2] = 48 + (value/10000) % 10;
    ptr1[4 + offset2] = 48 + (value/1000) % 10;
    ptr1[6 + offset2] = 48 + (value/100) % 10;
    ptr1[8 + offset2] = 48 + (value/10) % 10;
    ptr1[10+ offset2] = 48 + (value/1) % 10;
    while(1);
    ...
}

And the output of this is 000000.

Qemu window showing 000000

On a normal Linux machine, it works with no problem showing me the memory location.

Also, I have noticed that when I try to make the function pointer and then call the function pointer, it does indeed work; however, when I try to get its value it just doesn't work. (&isr0 cannot be a problem then. It's the problem of somehow parsing it into int.)

Can anyone tell me why this happens, and how to fix it?

Steps to compile
i686-elf-gcc -nostdlib -O3 -ffreestanding -Wall -Wextra -m32 -c kernel.c -o bin/stage4.bin
objcopy -O binary bin/stage4.bin bin/stage5.bin

Compile those two using:

nasm stage1.asm -f bin -o bin/stage1.bin

And then just cat it all together:

cat bin/stage1.bin bin/stage2.bin bin/stage5.bin > bin/stage3.bin
qemu-system-x86_64 -fda bin/stage3.bin -vga vmware  -d guest_errors -m 64M >> bin/a 2>&1

Solution

  • i686-elf-gcc -nostdlib -O3 -ffreestanding -Wall -Wextra -m32 -c kernel.c -o bin/stage4.bin 
    objcopy -O binary bin/stage4.bin bin/stage5.bin
    

    This won't work. gcc -c produces a relocatable object file, which you've misleadingly named stage4.bin instead of .o. It doesn't contain actual addresses of objects at the locations in memory where they need to be; rather, it puts in a placeholder (possibly 0), and has a separate relocation table to inform the linker of the name of the symbol whose address should go there. But you didn't actually link the file; you just objcopy'd into binary, which simply discards the relocation table and leaves the memory location occupied by the 0 placeholder.

    You have to actually run the linker on your object file to resolve all these references and build an executable, using an appropriate linker script. See https://wiki.osdev.org/Linker_Scripts for some examples. Then you can objcopy to binary after that.