我正在制作一个需要同时运行多个任务的应用程序。我不能使用线程等,因为应用程序应该在没有任何操作系统的情况下工作(即直接从引导扇区)。使用 x86 任务看起来有点矫枉过正(在逻辑和性能方面)。因此,我决定自己实现一个任务切换实用程序。我会保存处理器状态,调用任务代码,然后恢复以前的状态。所以我必须从内联汇编中进行调用。
下面是一些示例代码:
#include <stdio.h>
void func() {
printf("Hello, world!\n");
}
void (*funcptr)();
int main() {
funcptr = func;
asm(
"call *%0;"
:
:"r"(funcptr)
);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它在 icc 下完美编译,没有选项,gcc 和 clang 并产生“Hello,world!” 运行时。但是,如果我用 编译它icc main.c -ipo,它会出现段错误。
我反汇编了生成的代码icc main.c并得到以下内容:
0000000000401220 <main>:
401220: 55 push %rbp
401221: 48 89 e5 mov %rsp,%rbp
401224: 48 83 e4 80 and $0xffffffffffffff80,%rsp
401228: 48 81 ec 80 00 00 00 sub $0x80,%rsp
40122f: bf 03 00 …Run Code Online (Sandbox Code Playgroud) 我正在尝试制作一个适用于两种架构的引导加载程序:x86 和 PDP-11。主操作系统是为 PDP-11 兼容机器编写的,但从 x86 启动也应该可以工作,启动模拟器。
AFAIK,如果最后两个字节是, x86 加载第一个磁盘扇区0x7c00并跳转到那里。相反,如果第一个命令是且最后两个字节是 ,则 PDP-11 兼容机将第一个扇区加载到(八进制)并执行它。然而,由于一些硬件细节的原因,加载的数据实际上是颠倒的——例如,x86 读取的数据,另一台机器读取的数据。在这种情况下,这在某种程度上是一个功能,因为如果我制作最后两个字节,它们将适用于两台机器。0x55 0xaa0o20000NOP0xaa 0x550x120xed0x55 0xaa
总之,PDP-11兼容机需要前两个字节包含NOP命令,即0o000240,或0x00a0。数据被反转,因此 x86 实际上会读取0xff5f。
0x5f是 x86 中的真实命令。不幸的是,它是pop di. AFAIK,sp和ss值都没有指定,所以这个命令读取谁知道什么。
我的问题是:
0x0000:0x0000or 0xffff:0xffff?ss:sp指向读取不安全的内存映射硬件寄存器?如果是的话,如果我读了它们,会发生什么更糟糕的事情?我不想意外损坏笔记本电脑。ss:sp指向不可用的内存,即可能pop di触发总线错误?如果是,BIOS 将如何从中恢复,即它将重新启动、显示消息或执行其他操作?