小编Iva*_*anq的帖子

如何阻止 icc 消除从内联汇编中调用的函数

背景

我正在制作一个需要同时运行多个任务的应用程序。我不能使用线程等,因为应用程序应该在没有任何操作系统的情况下工作(即直接从引导扇区)。使用 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)

c optimization icc

7
推荐指数
0
解决办法
109
查看次数

在引导加载程序启动时读取堆栈安全吗?

背景

我正在尝试制作一个适用于两种架构的引导加载程序: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,spss值都没有指定,所以这个命令读取谁知道什么。

我的问题是:

  • 在实践中,我可以假设它们要么指向有效的堆栈,要么都设置为某个占位符,例如0x0000:0x0000or 0xffff:0xffff
  • 可能ss:sp指向读取不安全的内存映射硬件寄存器?如果是的话,如果我读了它们,会发生什么更糟糕的事情?我不想意外损坏笔记本电脑。
  • 可能ss:sp指向不可用的内存,即可能pop di触发总线错误?如果是,BIOS 将如何从中恢复,即它将重新启动、显示消息或执行其他操作?

x86 assembly bootloader x86-16 stack-pointer

5
推荐指数
0
解决办法
130
查看次数

标签 统计

assembly ×1

bootloader ×1

c ×1

icc ×1

optimization ×1

stack-pointer ×1

x86 ×1

x86-16 ×1