我对系统软件开发很感兴趣。几天来我一直在分析编译器的工作方式。编译器生成的汇编代码clc
有一个操作码f8
,我确信汇编上述助记符的汇编器会用其操作码替换f8
它的位置。
令我困扰的是这个阶段的后果(我知道中间的链接阶段)。
我的意思是,这个阶段之后究竟会发生什么?假设最终的可执行文件是一个原始二进制文件。这是否意味着操作码f8
被转换成二进制数据1111 1000
并存储在文件中?
如果是这样的话,为什么我不能使用普通文本编辑器(比如记事本)查看二进制文件的二进制内容——毕竟它是“0”和“1”对吧?
答案1
首先,始终使用正确的工具来完成工作。文本编辑器查看二进制文件就像用刀子钉钉子一样。使用任何 HEX 查看器/编辑器来完成此类任务,或者最好使用了解相关二进制文件内部情况的工具。如果我们谈论的是 CPU 的操作码,那么类似IDA Pro 免费或者奥利数据库对于分析可执行文件的内部结构很有用。
这是否意味着操作码
f8
被转换成二进制数据1111 1000
并存储在文件中?
正如@Mokubai 正确指出的那样 - 0xF8
与 是相同的数字1111 1000
,一个以十六进制表示,最后一个以二进制表示。它与十进制中的数字 248 相同。
如果您从 CPU 操作码手动创建可执行代码(或编译汇编程序源代码),那么 i386 CPU 将识别0xF8
(或0b11111000
248 - 全部相同)为CLC
指令。
编译器生成的汇编代码
clc
有一个操作码f8
,我确信汇编上述助记符的汇编器会用其操作码替换f8
它的位置。
确实如此,除了“编译器生成的汇编代码”。我只是想确保你正确理解“汇编代码”和操作码之间的区别。操作码是 CPU 可以理解的确切语言,它只是数字(当 CPU 助记符(又称汇编程序)的翻译器还是一个梦想时,这就是我们编写第一台计算机的方式)
如今,我们主要使用“直接”编译将高级编程语言直接编译为可执行二进制文件,编译器如 C/C++/GoLang 可生成 CPU 操作码。
(我说的“直接编译”实际上并不正确,编译器在生成可执行二进制文件之前会执行多个步骤,但对于最终用户来说,这看起来就像我们开车一样,不需要知道汽油是如何转化为运动的)
正如@sawdust在评论中正确提到的,高级编程语言可以使用不同的策略来创建CPU操作码。例如,您可以分析gcc
编译器如何通过告诉它生成用于制作操作码(目标代码)的汇编代码来制作操作码
gcc -S -o myprogram.asm myprogram.c
如果是这样的话,为什么我不能使用普通文本编辑器(比如记事本)查看二进制文件的二进制内容——毕竟它是“0”和“1”对吧?
记事本使用另一种语言。它理解自己的“操作码” - ASCII,其他任何内容对记事本来说都是“希腊语”。