我对底层的东西了解不多。但是,据我所知,编译器生成的二进制文件中包含系统和库调用。
如果您既不进行任何系统调用也不调用任何库,那么二进制文件是否只是原始程序集,如果您在同一台机器上但在另一个操作系统上,则无需任何更改即可执行?还有什么可以将二进制文件链接到他们的操作系统?是否可以在没有任何系统调用的情况下编写跨平台的 Hello world asm 程序?是否需要访问内核空间因此不可能?
号
可执行文件有元数据,而不仅仅是原始机器代码,不同的操作系统使用不同的格式。 (除非您有 DOS .com
可执行文件;该格式没有元数据,只是以相对于操作系统选择的任何段的固定偏移量加载到内存中。)这使您可以获得有用的错误消息(而不是运行它并获得段错误)尝试在 x86-64 OpenBSD 或 Linux 上运行 x86-64 FreeBSD 可执行文件时,即使它们都使用相同的格式(ELF)。或者让操作系统透明地调用模拟器,例如 AArch64 硬件上的 macOS 如何通过 Rosetta 运行 x86-64 二进制文件,或者 Linux 通过
binfmt-misc
调用 QEMU,而不是为错误的架构加载机器代码并拥有 CPU很快就会出现非法指令或页面错误或其他问题的故障。
write
系统调用或 MessageBoxA 等效的 WinAPI 调用,或类似的东西。系统调用 ABI 是特定于操作系统的。例如在 x86-64 Linux 上,
mov eax, 1
/
syscall
是一个
write
系统调用。在 x86-64 MacOS 上,
mov eax, 0x2000004
/
syscall
。这些都是类 Unix 操作系统; Windows 等其他系统甚至没有稳定的系统调用 ABI;在您自己的进程之外执行任何操作的唯一可移植(跨 Windows 版本)方法是调用 DLL 函数,这取决于可执行文件中特定于 Windows 的元数据。
连便携退出都是问题;通常这是通过退出系统调用完成的,因此是特定于操作系统的。但是,如果您的进程出现故障(例如,非法指令、访问错误地址或尝试运行特权指令),操作系统将终止您的进程。因为您不会进行较早的系统调用来设置处理程序或其他东西。
所以不,不是 Hello World;没有系统调用,你所能做的就是修改你自己的记忆;主流操作系统不会启动具有任何特殊内存区域的进程,内存映射到从外部可见的任何内容。
您可以通过诸如 CPU 温度、性能计数器或对其他进程的性能影响(例如内存带宽或您从共享 L3 缓存中驱逐数据的速度,或者在大量堆栈上循环)等边通道进行通信(泄露数据)空间与否)。不同的指令组合会使 CPU 升温更多或更少;您没有让进程休眠的选项(这需要系统调用),但是运行 x86
pause
指令的循环将使用比
vmulpd ymm0, ymm1, ymm2
指令块少得多的功率。 (256 位浮点乘法,或 FMA 可能更耗电。)这当然不能使“Hello World”出现在控制台中,除非您正在运行另一个经常检查 CPU 温度并一次收集几位输出的进程。该程序当然必须进行系统调用。
但是,如果您不关心最终出现在控制台中的“Hello World”,并且只想将数据传递给其他一些也不进行任何系统调用的进程,它也许可以运行定时测试,使用 x86 定时
rdtsc
之类的,也许是一个依赖于 L3 缓存命中的微基准测试,数据生产者可以运行一个循环来写入大量堆栈空间或者不接触内存。可能每比特输出花费 10 亿个 TSC 滴答,让读者有时间看看它发送了什么。 (你可以为你实际想要发送的任何数据想出协议。这个想法适用于共享 L3 缓存的任何一对 CPU 内核,因此大多数台式机/笔记本电脑 CPU 除了一些具有多个“核心集群”的 Ryzens (CCX))