首先,您当然必须拥有定义指令集(包括机器代码)的处理器文档。
接下来你会写一些不是死代码的东西:
unsigned int fun ( unsigned int a, unsigned int b )
{
return(a|b);
}
故意不使用 x86
Disassembly of section .text:
00000000 <fun>:
0: e1800001 orr r0, r0, r1
4: e12fff1e bx lr
然后您可以检查与文档相关的机器代码并了解这些指令的编码。
这一切都是微不足道的。
最大的问题是你打算如何运行这段代码?您说没有内核意味着没有操作系统,这意味着裸机,这意味着您必须启动处理器,这需要详细的处理器和系统(芯片/主板/媒体/等)信息。当您的计算机启动并运行或您的微控制器时,这显然是可能的(对于这种教育来说,这是明显更好的选择,避免 x86 作为第一个 ISA 也是一个不错的选择)。甚至更好的模拟器/模拟器,因为您有更好的可见性并且它是不可变砖的,其中硬件不难变砖,有时不难用糟糕的软件冒烟。
根据您的问题,您需要先爬行,然后再跑步,然后再步行。从如图所示的简单函数开始,您可以使用某些工具(gnu 是您的朋友,也是敌人,因为它需要时间来掌握,但它的功能非常丰富)使用机器代码编写并将其提供给汇编器
.globl fun
fun:
.inst 0xe1800001
.inst 0xe12fff1e
Disassembly of section .text:
00000000 <fun>:
0: e1800001 orr r0, r0, r1
4: e12fff1e bx lr
如果您不想使用汇编程序并想自己创建二进制文件,那么您必须阅读文件格式,许多已发布,即使/特别是如果您从头开始编写工具,这也是一项微不足道的任务做到这一点而不是依赖库,但这取决于你和文件格式。不确定你真正感兴趣的切线和研究项目有多少。它们都有价值,但你真正想学习的是什么和/或你的愿望的优先级是什么。
您可能需要数月至数年的工作,具体取决于您真正追求的目标。解决这个问题的最佳途径是首先使用可用的工具和沙箱,然后根据需要替换它们,而不是在没有任何现有工具的帮助的情况下从头开始编写所有内容。
您想制造更好的锤子,首先使用现有的锤子,决定您喜欢什么和不喜欢什么,然后自己制作。你不会在没有使用过的情况下就开始尝试创建一个并期待任何形式的成功。或者在任何合理的时间表内取得成功。
从头开始做所有事情的一个大问题是您需要将字节放入闪存或内存或某些媒体中,以便处理器可以获取并运行它们。如果没有一些工具,您可能无法做到这一点,一台具有操作系统的完整工作计算机,您可以在其中获取原始字节,一些能够对闪存进行编程并使用所有这些将您的原始位编程到闪存中的硬件工具。现在,您可能可以使用一些闪光灯(必须解决弹跳问题),例如在旧 DEC 或其他东西的前面,并通过用于对设备进行编程的协议来切换您的方式,因此只需要铅笔/笔和纸以及开关和接线作为工具。
您最好使用指令集模拟器并根据它支持的文件格式,滚动您自己的二进制创建工具或使用汇编程序或类似的东西来制作文件以提供给 sim。或者甚至更好地制作自己的模拟器,这样您就可以比大多数经验丰富的专业人员更好地学习指令集......然后当然您可以创建自己的二进制创建工具来匹配。如果您没有采用现有的指令集和工具集并学习在汇编/机器语言级别进行编程,查看它是如何工作的,查看使用/生成的指令,并使用文档查看编码,那么您很可能会失败,等等
大多数新指令集软件人员可以直接访问芯片人员(沿着大厅走到人员办公室,或打电话给他们),并可以询问有关指令编码的问题。由于您不能这样做,因此您必须询问现有的、已调试的工具,因此正如我在上面开始的那样,询问编译器,询问汇编程序。然后对其进行反汇编,然后假设汇编器生成了正确的指令并将其与处理器文档进行比较(了解工具和文档都可能存在错误,因此您必须解决该问题)。