操作系统Lab笔记——为什么mpentry_start到mp_main是间接调用?

本文内容分析于2023年12月18日。今整理成文。

先看源代码:kern/mpentry.S:76

asm
# Call mp_main(). (Exercise for the reader: why the indirect call?)
movl    $mp_main, %eax
call    *%eax

灵魂提问:why the indirect call?

直接调用的call指令,使用%eip相对寻址。而call指令的偏移量,是在链接时确定的。但mpentry.S链接地址和运行地址不一样(复制到0x7000再执行),这使得链接时确定的偏移量在运行时是错误的。因此,只能使用间接调用,将mp_main的绝对地址加载到%eax中,然后call *%eax

知道了原理,就可以改动链接脚本,使mpentry_startmp_main通过call指令直接调用。

上面两句汇编改成:

asm
# Call mp_main(). (Exercise for the reader: why the indirect call?)
movl    $mp_main, %eax
call    *%eax
call    true_mp_main // [!code ++]

链接脚本kern/kernel.ld

txt
.text : AT(0x100000) {
    *(.text .stub .text.* .gnu.linkonce.t.*)
    PROVIDE(true_mp_main = mp_main + (0xF0100000 + mpentry_start - 0x7000)); // [!code ++]
    *(.text .stub .text.* .gnu.linkonce.t.*)
}
Todo List
Valaxy v0.28.4 驱动|主题-Yunv0.28.4