c - 我无法理解我们看到的字符之间的抽象以及计算机如何处理它们

标签 c binary operating-system kernel low-level

这是相当低的水平,英语不是我的母语所以请放轻松。

想象一下你在 bash 中,命令提示符出现在你的屏幕前。

当您键入 ls 并按回车键时,您实际上是在从您的计算机向 cpu 01101100 01110011 00001010(即:l s 换行符)发送一些字节,对吗?键盘 Controller 将字节发送给 cpu,cpu 告诉操作系统收到了哪些字节。

所以如果我理解正确的话,我们的硬盘(或内存)中有一个名为 01101100 01110011 的应用程序?那是一个文件,而且是一个可执行文件。但是操作系统如何在驱动器或内存中找到01101100 01110011呢?

另外我想把这个问题扩展到函数。例如,我们说 C 标准库有一个名为 printf 的函数。一个函数怎么能有一个在文件中的名字呢?好的,我知道 printf 函数的实现是特定于 cpu 和操作系统的,并且是一些位于内存或硬盘驱动器中某处的机器指令。但我不明白我们是如何做到的?

当我链接需要执行 printf 的代码时,如何找到它?我假设操作系统对函数的名称一无所知,或者它不知道?

最佳答案

Koray,用户@DrKoch 给出了一个很好的答案,但我想添加一些抽象。

首先,ASCII是一种编码。它是一个表,其中一列是位模式,下一列是字母。位模式恰好是一个字节长(不包括“宽字符”等)。如果我们知道一个字节应该代表一个字符,那么我们可以在表中查找字节的位模式。打印函数(还记得点阵打印机吗?)接收一个字符(一个字节)并指示点阵打印机的针以某种有序的方式敲打在纸上,看,形成了一个人类可以阅读的字母。设计 ASCII 码是因为计算机不使用字母进行思考。还有其他的编码,比如EBCDIC,只是表示表不同罢了。

现在,如果我们不知道字节是某种代码中字母的表示,那么我们就迷路了,字节可能只是表示数字。我们可以将一个字节与另一个字节相乘。所以你可以将 a' 与 'p' 相乘,得到 97 * 112= 10864。那个男性有感觉吗?只有我们知道字节代表数字,如果字节代表字符是无意义的。

下一个级别是我们将所有应该代表字母(字符)的字节序列称为“字符串”,并且我们开发了可以搜索、获取和追加字符串的函数。一个字符串有多长?在 C 语言中,我们一致认为,当我们看到位模式全为零的字节(空字符)时,就到达了字符串的末尾。在其他语言中,字符串表示可以具有长度成员,因此不需要终止空字符。

这是“协议(protocol)堆叠”的示例。另一个例子(指你之前问的一个问题)是中断:硬件在电路板上定义了一条物理线作为中断线(协议(protocol))。它连接到处理器的中断引脚(协议(protocol))。线路上的信号(例如来自外部设备)导致处理器保存寄存器的当前状态(协议(protocol))并将控制权转移到预定义的内存位置(协议(protocol)),其中放置了中断处理程序(协议(protocol))来处理来自外部设备的请求。在这个堆叠的例子中,我们可以在功能应用上有很多层次,在各个门和晶体管下面有很多层次(以及多少伏特是“1”和多少伏特是“0”的基本定义,以及在确定看到 1 或 0 之前必须观察该电压多长时间)。

只有理解了所有这些层级都只是协议(protocol),才能理解一台计算机。并且只有了解所有这些级别只是人类之间达成的协议(protocol),才能从中抽象出来并且不被这些基础所困扰(工程师会照顾它们)。

关于c - 我无法理解我们看到的字符之间的抽象以及计算机如何处理它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30302970/

相关文章:

c++ - C++ 中的 while 循环中始终存在变量

c - 在c中如何为字符串文字分配内存,我们是否需要释放它?

c - 为什么在 main 中打印 'x' 的值,而它可能在从 abc() 出来时已被释放?

c - 从 C 程序执行终端

objective-c - 将 C 转换为 Obj-C 文件读取代码

java - 字符串中 1 和 0 的最大交替子序列

Python: boolean 列表到二进制字符串

assembly - 如何判断电脑是否有组装中的XT/AT键盘?

multithreading - 操作系统如何确定应为每个线程分配多少堆栈空间?

linux-kernel - LinuxBoot 在固件阶段与 Coreboot 有何不同?