1

Here is my code:

  1. interruptstubs.s:
.set IRQ_BASE, 0x20

.section .text

.extern _ZN16InterruptManager15handleInterruptEhj

.global _ZN16InterruptManager22IgnoreInterruptRequestEv

.macro HandleException num
.global _ZN16InterruptManager16HandleInterruptException\num\()Ev
_ZN16InterruptManager16HandleInterruptException\num\()Ev:
    movb $\num, (interruptnumber)
    jmp int_bottom
.endm

.macro HandleInterruptRequest num
.global _ZN16InterruptManager26HandleInterruptRequest\num\()Ev
_ZN16InterruptManager26HandleInterruptRequest\num\()Ev:
    movb $\num+IRQ_BASE, (interruptnumber)
    jmp int_bottom
.endm

HandleInterruptRequest 0x00
HandleInterruptRequest 0x01

int_bottom:
    pusha
    pushl %ds
    pushl %es
    pushl %fs
    pushl %gs


    pushl %esp
    push (interruptnumber)
    call _ZN16InterruptManager15handleInterruptEhj
    movl %eax, %esp

    popl %gs
    popl %fs
    popl %es
    popl %ds
    popa

_ZN16InterruptManager22IgnoreInterruptRequestEv:
    iret


.data
    interruptnumber: .byte 0
  1. interrupts.h:
class InterruptManager
{
public:
    static uint32_t handleInterrupt(uint8_t interruptNumber, uint32_t esp);
};
  1. interrupts.cpp:
#include "interrupts.h"

uint32_t InterruptManager::handleInterrupt(uint8_t interruptNumber, uint32_t esp)
{
    printf((char *)" INTERRUPT");
    return esp;
}

I compile/assemble/link with these commands:

as --32 -o loader.o loader.s
g++ -m32 -Iinclude -fno-use-cxa-atexit -fleading-underscore -fno-exceptions -fno-builtin -nostdlib -fno-rtti -fno-pie -o gdt.o -c gdt.cpp
g++ -m32 -Iinclude -fno-use-cxa-atexit -fleading-underscore -fno-exceptions -fno-builtin -nostdlib -fno-rtti -fno-pie -o port.o -c port.cpp
g++ -m32 -Iinclude -fno-use-cxa-atexit -fleading-underscore -fno-exceptions -fno-builtin -nostdlib -fno-rtti -fno-pie -o interrupts.o -c interrupts.cpp
as --32 -o interruptstubs.o interruptstubs.s
g++ -m32 -Iinclude -fno-use-cxa-atexit -fleading-underscore -fno-exceptions -fno-builtin -nostdlib -fno-rtti -fno-pie -o kernel.o -c kernel.cpp
ld -melf_i386 -no-pie -T linker.ld -o mykernel.bin loader.o gdt.o port.o interrupts.o interruptstubs.o kernel.o

the whole code structure is like this above. uint32_t is defined before and here I didn't show it because I don't think it caused problem.

Now when calling the method 'handleInterrupt()' from the .cpp file in my asm code, it has compile error:

ld: interruptstubs.o: in function `int_bottom':
(.text+0xf): undefined reference to `InterruptManager::handleInterrupt(unsigned char, unsigned int)'

I wonder why it didn't work when linking because I have declared .extern _ZN16InterruptManager15handleInterruptEhj in front of the file.

I have searched almost everything on the Internet and didn't get the answer.

4
  • 2
    Can you please show the command lines you're using to compile, assemble and link? Commented Mar 3, 2023 at 3:12
  • Yes, we have a Makefile to struct the project. We have a github repository, you can see files in this repository. Thank you for taking your time! Commented Mar 3, 2023 at 4:42
  • 2
    Is there a reason you are compiling with -fleading-underscore? You are telling G++ to use a leading underscore which in the case of the classes ends up using a double underscore __ on member names. You'd have to modify your assembly code in interruptstubs.s to use __ instead of _ which is the cause of the problem. I'd recommend not using -fleading-underscore but there might be a reason you are? Commented Mar 3, 2023 at 5:13
  • 2
    I am so careless, and a beginner to the assemble language. The problem has been solved, thank you sir! @Michael Petch Commented Mar 3, 2023 at 5:31

1 Answer 1

0

Since you are compiling with -fleading-underscore and additional _ is being prepended to identifiers. In the case of class functions and member variables this results in two underscores __ appearing.

The assembly code in interruptstubs.s will have to take that into account:

.set IRQ_BASE, 0x20

.section .text

.extern __ZN16InterruptManager15handleInterruptEhj

.global __ZN16InterruptManager22IgnoreInterruptRequestEv

.macro HandleException num
.global __ZN16InterruptManager16HandleInterruptException\num\()Ev
__ZN16InterruptManager16HandleInterruptException\num\()Ev:
    movb $\num, (interruptnumber)
    jmp int_bottom
.endm

.macro HandleInterruptRequest num
.global __ZN16InterruptManager26HandleInterruptRequest\num\()Ev
__ZN16InterruptManager26HandleInterruptRequest\num\()Ev:
    movb $\num+IRQ_BASE, (interruptnumber)
    jmp int_bottom
.endm

HandleInterruptRequest 0x00
HandleInterruptRequest 0x01

int_bottom:
    pusha
    pushl %ds
    pushl %es
    pushl %fs
    pushl %gs


    pushl %esp
    push (interruptnumber)
    call __ZN16InterruptManager15handleInterruptEhj
    movl %eax, %esp

    popl %gs
    popl %fs
    popl %es
    popl %ds
    popa

__ZN16InterruptManager22IgnoreInterruptRequestEv:
    iret


.data
    interruptnumber: .byte 0

Another option for your code would be omit the option -fleading-underscore and amend your entire codebase accordingly. Using a generic ELF cross compiler would help as it removes the differences between platforms that may require global identifiers to be prepended with an extra _ (IE Windows, and MacOS tool chains)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.