如何使用APM从保护模式关闭?

时间:2019-07-20 08:02:24

标签: c++ assembly kernel power-management

我的内核使用GRUB引导,因此它在受保护的模式下启动,并且A20线已被解锁。然后,它重新路由设备irqs并加载自己的设备。现在我要关闭设备。可以使用APM完成此操作,但是只能从实模式启用APM,因此我编写了切换到实模式然后连接到APM的代码,将其版本设置为1.1 / 1.2,为所有设备启用它并关闭所有设备:

asm volatile("cli\n"
           "mov eax, cr0\n"
           "and al, not 1\n"
           "mov cr0, eax\n"
           "sti");

  asm volatile("mov ah, 0x53\n"
           "mov al, 0x01\n"
           "xor bx, bx\n"
           "int 0x15");

  asm volatile("mov ah, 0x53\n"
           "mov al, 0x0e\n"
           "mov bx, 0x0000\n"
           "mov ch, 0x01\n"
           "int 0x15");

  asm volatile("mov ah, 0x53\n"
           "mov al, 0x08\n"
           "mov bx, 0x0001\n"
           "mov cx, 0x0001\n"
           "int 0x15");

  asm volatile("mov ah, 0x53\n"
           "mov al, 0x07\n"
           "mov bx, 0x0001\n"
           "mov cx, 0x3\n"
           "int 0x15");

在运行此代码后,计算机也重新启动,并且在使用QEMU时收到启动错误(无效的“幻数”),而在使用真实计算机时,它会重新启动。

1 个答案:

答案 0 :(得分:2)

GNU风格的内联汇编要求保留所有不在输出或破坏列表中的寄存器,因此更改为实模式将破坏编译器生成的代码。使用单个asm语句解决此问题,或使用单独的程序集文件。

您尝试进入32位实模式,需要先切换到16位模式,然后再切换到实模式。

您需要使用远跳将CS设置为适合实模式的值,否则中断的第一个返回将到达错误的地址。

您可以在GRUB源代码中找到从32位保护模式切换到实模式的示例。