【问题标题】:How to shutdown from protected mode using APM?如何使用 APM 从保护模式关机?
【发布时间】:2019-11-29 01:30:40
【问题描述】:

我的内核使用 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 时我收到启动错误(无效的“幻数”),而在使用真机时它只是重新启动。

【问题讨论】:

  • 您是否使用 LIDT 重置了实模式中断?
  • 它要复杂得多。此答案中有一个完整的 Multiboot 示例,它切换到实模式以执行一些 vbe 调用(然后返回到保护模式)。 stackoverflow.com/a/41731180/3857942 。当然,您不必担心在关闭时恢复状态以返回保护模式的所有代码。

标签: c++ assembly kernel power-management


【解决方案1】:

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

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

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

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

【讨论】:

  • 如何跳转到0x15中断?
  • 不,跳到你自己的代码,两次。首先进入 16 位模式(对 16 位段使用段描述符),然后在离开保护模式后。
  • @TimothyBaldwin :当然在这种情况下不需要退出保护模式,因为机器正在关闭。
猜你喜欢
  • 2019-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 2019-03-27
相关资源
最近更新 更多