assembly - 在引导加载程序中使用的正确调用约定是什么?

标签 assembly operating-system x86-16 bootloader calling-convention

我正在尝试编写一个引导加载程序和一个非常原始和基本的内核,以了解裸机编码实践和技术。无论如何,我正在使用 NASM 编写我的 bootstrap 。我的代码正在运行,但我对要使用的调用约定有疑问。
我只是通过运行 NASM 来编译我的引导加载程序:nasm bootloader.asm -o bootloader .
在我的汇编代码中,我编写了类似 BlDisplayString 的函数。通过 BIOS 中断显示字符串 int 0x10AH = 0x13 .我正在尝试模拟 __fastcall通过在 CX, DX, STACK 中传递参数来调用约定.这是在 16 位代码中使用的正确调用约定标准吗?当我调用这些函数时,CPU 未处于保护模式并且仍处于实模式。

最佳答案

CPU 不在乎,做任何方便和可维护的事情。 “正确性”的唯一判断者是您,如果您不尝试链接到由 C 编译器生成的任何代码。
但是,是的,注册 args 通常是一个好主意,带有调用破坏的 AX、CX、DX。如果您愿意在每个 rep 之前设置它,让 ES 被调用可能会很方便,以避免让函数保存/恢复它。 - 字符串函数。
在与 BIOS int 对齐的寄存器中传递参数调用希望它们可以在包装器代码中保存一些指令。
您甚至可以在每个函数的基础上使用自定义调用约定,但这更难记住/记录。对于仅从一个函数(但在该函数中的多个位置)或从一个文件中的几个类似函数调用的本地辅助函数很有用。在注释中,注册输入、输出和破坏的文档(用作没有保存/恢复的暂存空间)。
对不同类型的函数有几个不同的调用约定是 1 个固定约定与每个函数不同的约定之间的中间地带。
在 FLAGS 中返回 bool 条件对于 asm 很方便,尤其是当您希望调用者在其上进行分支时。或者对于像 memcmp 这样的函数, 以 cmp al, dl 结尾或任何让您的调用者在相等或更大/更少上分支的东西,无论它想读取哪个标志。所有这些都没有像 C 函数那样实际生成 +/0/- 返回值的成本。
CodeGolf.SE 上的答案 Tips for golfing in x86/x64 machine code如果您全力以赴编写小代码而完全不关心函数之间的可维护性或一致性,那么将详细介绍您可能会做什么。
如果您想将更多代码放入 512 字节的第一阶段引导加载程序,或放入更少的额外扇区,您通常可以在不影响可读性的情况下节省一些字节。
更少的指令通常更容易阅读。 (不过,这并不总是与较小的机器代码大小相同。)

关于assembly - 在引导加载程序中使用的正确调用约定是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62737202/

相关文章:

macos - OSX 中 XNU 内核的系统调用列表和文档

performance - 保存左移(SHL)中偏移的位

assembly - SHL和SAL在80x86中的区别

linux - 限制在 sys_read 上读取的字符数

linux - 使用 $ - x 时我们在汇编中减去多少位(或字节)

c - 调用fork()时程序陷入死锁

assembly - 如何用汇编语言在定义双字中存储4个字符?

assembly - 以 8086 读取文件,直到文件结束

string - 子字符串搜索程序总是返回 false

operating-system - 内核和用户线程之间的关系