How to statically define an IDT with low-16 addresses in a 32-bit kernel (with gcc inline assembly)

Viewed 133

I have the following code in NASM which is shortened for the question:

idt_start:
int0:
      dw isr0
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
idt_end:
idtr:
    dw idt_end - idt_start - 1
    dd idt_start
isr0:

Normally I have 47 of these entries 32 for the protected mode exceptions and 15 to map the IRQs. I'm setting up an IDT to manage interrupts from my bootloader.

The problem arises when I try to port this code to C++ inline assembly.

I have 2 files kernel.cpp:

#include "idt.h"

void kmain(){
    defineIDT();
    halt:;
    asm("hlt");
    goto halt;
}

and idt.cpp:

void defineIDT(){
    asm(
    "idt_start:\n\t"
    "int0:\n\t"
    ".hword isr0\n\t"
    ".hword 0x0008\n\t"
    ".byte 0x00\n\t"
    ".byte 0b10001110\n\t"
    ".hword 0x0000\n\t"
    "idt_end:\n\t"
    "idtr:\n\t"
    ".hword idt_end - idt_start - 1\n\t"
    ".word idt_start\n\t"
    "isr0:\n\t"
    );
    return;
}

I'm using g++ to compile my code with g++ -static -ffreestanding -nostdlib -znoexecstack -mno-red-zone -s -m32 kernel.cpp idt.cpp -okernel.o

I get an error saying relocation truncated to fit: R_386_16 against `.text'. It is because of the .hword isr0, .hword idt_end - idt_start - 1 and .word idt_start lines. I don't see how else to implement this.

1 Answers

I ended up doing the following:

I initialised the IDT with NASM.

extern routine33

bits 32

lidt[idtr]

sti

halt:
hlt
jmp halt

idt_start:
int0:
      dw isr0
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int1:
      dw isr1
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int2:
      dw isr2
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int3:
      dw isr3
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int4:
      dw isr4
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int5:
      dw isr5
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int6:
      dw isr6
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int7:
      dw isr7
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int8:
      dw isr8
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int9:
      dw isr9
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int10:
      dw isr10
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int11:
      dw isr11
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int12:
      dw isr12
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int13:
      dw isr13
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int14:
      dw isr14
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int15:
      dw isr15
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int16:
      dw isr16
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int17:
      dw isr17
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int18:
      dw isr18
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int19:
      dw isr19
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int20:
      dw isr20
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int21:
      dw isr21
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int22:
      dw isr22
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int23:
      dw isr23
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int24:
      dw isr24
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int25:
      dw isr25
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int26:
      dw isr26
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int27:
      dw isr27
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int28:
      dw isr28
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int29:
      dw isr29
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int30:
      dw isr30
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int31:
      dw isr31
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int32:
      dw isr32
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int33:
      dw isr33
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int34:
      dw isr34
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int35:
      dw isr35
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int36:
      dw isr36
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int37:
      dw isr37
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int38:
      dw isr38
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int39:
      dw isr39
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int40:
      dw isr40
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int41:
      dw isr41
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int42:
      dw isr42
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int43:
      dw isr43
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int44:
      dw isr44
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int45:
      dw isr45
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int46:
      dw isr46
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
int47:
      dw isr47
      dw 0x0008
      db 0x00
      db 10001110b
      dw 0x0000
idt_end:
idtr:
    dw idt_end - idt_start - 1
    dd idt_start

isr0:
iret
isr1:
iret
isr2:
iret
isr3:
iret
isr4:
iret
isr5:
iret
isr6:
iret
isr7:
iret
isr8:
iret
isr9:
iret
isr10:
iret
isr11:
iret
isr12:
iret
isr13:
iret
isr14:
iret
isr15:
iret
isr16:
iret
isr17:
iret
isr18:
iret
isr19:
iret
isr20:
iret
isr21:
iret
isr22:
iret
isr23:
iret
isr24:
iret
isr25:
iret
isr26:
iret
isr27:
iret
isr28:
iret
isr29:
iret
isr30:
iret
isr31:
iret
isr32:
iret
isr33:    ;mappped to IRQ 1 for Keyboard interrupt
call routine33
iret
isr34:
iret
isr35:
iret
isr36:
iret
isr37:
iret
isr38:
iret
isr39:
iret
isr40:
iret
isr41:
iret
isr42:
iret
isr43:
iret
isr44:
iret
isr45:
iret
isr46:
iret
isr47:
iret

Then I wrote a C++ function in idt.cpp:

void print(){
    asm("movw $0x0770, (0xb8000)");
}

extern "C" void routine33(){
    print();
    return;
}

I compile and link the result with a bash script:

#!/bin/bash

g++ -static -ffreestanding -znoexecstack -nostdlib -mno-red-zone -s -c -m32 idt.cpp -oidt.o

nasm -felf32 second_stage_bootloader.asm -osecond_stage_bootloader.o

ld -melf_i386 -static -pie --no-dynamic-linker -nostdlib --strip-all -Ttext=0x8000 second_stage_bootloader.o idt.o -o kernel.elf

objcopy --only-section=.text --output-target binary kernel.elf kernel.bin

dd if=/dev/zero of=disk.img bs=512 count=100 && dd if=bootloader.bin of=disk.img conv=notrunc && dd if=kernel.bin seek=1 bs=512 of=disk.img conv=notrunc

Then I load the resulting plain binary to RAM in my bootloader using BIOS interrupts to 0x8000. I jump to the code using jmp 0x08:0x8000.

I launch the whole thing with:

qemu-system-x86_64 -drive file=disk.img,format=raw,index=0,media=disk -s.

When I press a key it prints a white 'p' at 0xb8000.

Related