首页 > 解决方案 > gcc 错误:“无法找到要溢出的寄存器”(操作系统开发人员的内联汇编存在问题)

问题描述

所以伙计们,我正在学习如何在英特尔的 80386 中制作调度程序,所以请不要杀了我 :),我有以下混合了 C 和 inline-asm 的代码:

__INT_HANDLERS_SECTION__ static void saveTaskContext(_str_TSS * str_TSS_task)
{
    register uint32 * eax       asm ("eax");
    register uint32 * ebx       asm ("ebx");
    register uint32 * ecx       asm ("ecx");
    register uint32 * edx       asm ("edx");

    register uint32 * esi       asm ("esi");
    register uint32 * edi       asm ("edi");
    register uint32 * ebp       asm ("ebp");
    register uint32 * esp       asm ("esp");

    asm volatile("mov eax,gs");
    str_TSS_task->GS = *eax;

    asm volatile("mov eax,fs");
    str_TSS_task->FS = *eax;

    asm volatile("mov eax,ds");
    str_TSS_task->DS = *eax;

    asm volatile("mov eax,ss");
    str_TSS_task->SS = *eax;

    asm volatile("mov eax,es");
    str_TSS_task->ES = *eax;

    asm volatile("mov eax,cr3");
    str_TSS_task->ES =  *eax;

    str_TSS_task->EDI = * edi;
    str_TSS_task->ESI = * esi;
    str_TSS_task->ESP = * esp;

    asm volatile("pop edx");
    str_TSS_task->EDX = *edx;

    asm volatile("pop ecx");
    str_TSS_task->ECX = *ecx;   

    asm volatile("pop ebx");
    str_TSS_task->EBX = *ebx;   

    asm volatile("pop eax");
    str_TSS_task->EAX = *eax;   

    asm volatile("pop eax");
    str_TSS_task->EFLAGS = *eax;    

    asm volatile("pop eax");
    str_TSS_task->CS = *eax;    

    asm volatile("pop eax");
    str_TSS_task->EIP = *eax;

    str_TSS_task->EBP = *ebp;

    return;
}  // <------------------------- LINE 515 !!!

我期待保存寄存器的值(正如函数名称所说),但是当我尝试编译时,我得到下一个 gcc 错误:

src/handlers.c: In function ‘saveTaskContext’:
src/handlers.c:515:1: error: unable to find a register to spill
 }
 ^
src/handlers.c:515:1: error: this is the insn:
(insn 7 92 93 2 (set (reg:SI 146 [orig:88 D.1975 ] [88])
        (mem:SI (reg/f:SI 145 [orig:87 D.1974 ] [87]) [0 *_2+0 S4 A32])) src/handlers.c:470 90 {*movsi_internal}
     (expr_list:REG_DEAD (reg/f:SI 145 [orig:87 D.1974 ] [87])
        (nil)))
src/handlers.c:515: confused by earlier errors, bailing out

任何想法如何解决它?我真的很感激:)

编辑:我忘了说在弹出之前我已经在堆栈中(按自上而下的顺序)EIP、CS、EFLAGS、EAX、EBX、ECX 和 EDX

标签: cgccintelinline-assemblycpu-registers

解决方案


i386 只有八个通用寄存器。您将特定角色分配给所有这些角色。结果,GCC 无法找到可行的寄存器分配。(它需要一些寄存器来实现间接加载和存储。)此外,函数序言中使用了 ESP 和 EBP,并且可能在您的代码运行之前已被破坏。一个被调用的寄存器变量eax包含一个指向然后读取的值的指针也很奇怪。

您必须在单独的汇编程序例程中编写此代码,而不是作为 C 内联汇编。也不清楚您是否可以通过 ABI 调用约定实现您想要的。


推荐阅读