03|计算单元:运算符是如何工作的?
该思维导图由 AI 生成,仅供参考
C 运算符的分类
- 深入了解
- 翻译
- 解释
- 总结
C语言中的运算符在编译器中的实现方式是程序员们需要了解的重要技术细节。本文详细介绍了C语言中的运算符分类及其在编译器中的实现方式。根据最新的C17标准,C语言共有48个运算符,包括算数、关系、位、赋值等七类。文章通过示例代码和对应的汇编代码,详细介绍了加法、大于号和按位或运算符的实现方式,以及相关的汇编指令。此外,还介绍了FLAGS寄存器和标志位的概念,以及在比较指令执行后引起的CPU状态变化。在高编译优化等级下,编译器实现这些运算符的基本逻辑仍然不变。文章还介绍了逻辑与运算符的实现方式,包括条件跳转指令和高优化等级下的实现方式,以及成员访问运算符的实现细节。总的来说,本文通过深入的技术讲解,帮助读者了解了C语言中运算符在编译器中的实现方式,为读者提供了深入的技术知识。文章还介绍了逻辑与运算符的实现方式,包括条件跳转指令和高优化等级下的实现方式,以及成员访问运算符的实现细节。总的来说,本文通过深入的技术讲解,帮助读者了解了C语言中运算符在编译器中的实现方式,为读者提供了深入的技术知识。
《深入 C 语言和程序运行原理》,新⼈⾸单¥59
全部留言(20)
- 最新
- 精选
- 青鸟飞鱼问一个比较困惑的问题,学习c语言,真的要了解汇编吗
作者回复: 其实对于日常开发来说,不了解汇编并不会有太大的影响,因为这也是 C 语言被创造出来的目的之一。但计算机知识其实是成体系的,如果你想要“知其然,并知其所以然”,那了解汇编是一个必要的过程。
2021-12-1215 - =例如b = (a==3?3:2)。 三目运算符的汇编实现中,采用了cmp指令来比较a与3的大小,接着使用cmov指令根据cmp后的FLAGS寄存器的状态位的值,来决定b的值是3还是2。
作者回复: 没错!关于 cmove 指令的更多细节我们会在第 18 讲再深入讨论。
2021-12-115 - 无名氏请教下老师,这个汇编和c语言颜色对应的图是咋生成的😄
作者回复: 可以参考这里哈:https://godbolt.org/
2022-05-093 - ppd0705使用 `gcc -S` 得到的汇编代码风格不一样,请问要如何得到文章中的汇编代码风格呢?
作者回复: 可以尝试用 `objdump -M intel -d ./foo` 这个命令哈。
2022-01-2823 - Nuyoahmov edx, DWORD PTR [rbp-8] mov eax, DWORD PTR [rbp-4] cmp edx, eax cmovge eax, edx mov DWORD PTR [rbp-12], eax 自己理解是cmovage对应? cmp用来比较两个操作数的大小 最后的mov汇编指令将满足条件的操作数以32位存入寄存器相应位置
作者回复: 没错哈!
2021-12-262 - 阿锭啊阿滨啊L3问题:为什么还要and 1呢?前面不是赋值要么0要么1了吗?还会是其他值吗?
作者回复: 想想 `bool` 这个关键字?
2022-01-0931 - 白凤凰L3的思考题,为什么我的执行是这个样子的?没有and哪句指令。 .L3: mov BYTE PTR [rbp-1], al movzx eax, BYTE PTR [rbp-1] mov esi, eax mov edi, OFFSET FLAT:.LC0 mov eax, 0 call printf
作者回复: 是用的同一段 C 代码吗?具体使用的编译器和环境是怎样的呢?如果方便的话,也可以完整地回复一下汇编代码哈。
2021-12-221 - 没有軒的筝“程序会按顺序将位于栈内存中的变量 x 和 y 的值与数值 0 进行比较。若其中的某个比较结果相等,程序执行将会直接跳转到标签 “.L2” 的所在位置“,这句话是什么意思的?是变量x和y的值分别与0进行比较吗?还有“某个比较结果相等”是变量x和变量y分别与0比较后的两个结果吗?
作者回复: 实际上就同汇编代码展示的那样,rbp-20 与 rbp-24 位置上分别存放着变量 x 与 y 的值。而对应的两行 cmp 指令执行时,会分别将这两个值与数值 0 进行比较,当其中任意一个变量的值与 0 相等时,则程序紧接着会执行标签 .L2 处的指令。
2022-03-15 - 丶je不是相等才跳转吗,结果相等,ZF会置1吧,上面说je判断ZF是否为0,若为0则跳转
作者回复: 感谢指正!
2022-03-09 - zxk逻辑运算符优化后的那段汇编: test edi, edi ; edi <- x. setne al test esi, esi ; esi <- y. setne sil movzx esi, sil and esi, eax 为什么要使用 movzx 进行零扩展呢,直接 and al sil 或者 and esi eax 不是可以节省一条指令么?
作者回复: 因为我们不能直接假定 sil 的高位字节都是 0,所以需要用零扩展来“扩大”值的宽度。而之所以要用 esi 寄存器而不是 sil 的一个可能原因是:通常来说,机器指令在以“自然大小”为长度的寄存器(这里就是 esi)上进行相应的数据操作,效率是最高的。因此,即使少执行一条指令,也并不见得开销就一定最小。当然,这里也只是猜测,实际上只是编译器的一种实现上的选择。
2022-01-16