图解 Google V8
李兵
前盛大创新院高级研究员
26763 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

10 | 机器代码:二进制机器码究竟是如何被CPU执行的?

IO读/写指令
跳转指令
更新指令
存储指令
加载指令
读写速度
内存地址
指令类型
通用寄存器
PC寄存器
CPU时钟周期
内存
汇编指令执行过程
栈帧
CPU执行指令
程序装载进内存
汇编代码执行流程
CPU执行二进制代码
二进制机器码执行流程

该思维导图由 AI 生成,仅供参考

你好,我是李兵。
在上一节我们分析了 V8 的运行时环境,准备好了运行时环境,V8 就可以执行 JavaScript 代码了。在执行代码时,V8 需要先将 JavaScript 编译成字节码,然后再解释执行字节码,或者将需要优化的字节码编译成二进制,并直接执行二进制代码。
也就是说,V8 首先需要将 JavaScript编译成字节码或者二进制代码,然后再执行
在后续课程中,我们会分析 V8 如何解释执行字节码,以及执行编译好的二进制代码,不过在分析这些过程之前,我们需要了解最基础的知识,那就是 CPU 如何执行二进制代码。
因为字节码的执行模式和 CPU 直接执行二进制代码的模式是类似的,了解 CPU 执行二进制代码的过程,后续我们分析字节码的执行流程就会显得比较轻松,而且也能加深我们对计算机底层工作原理的理解。
今天我们就要来分析下二进制代码是怎么被 CPU 执行的,在编译流水线中的位置你可以参看下图:
CPU执行二进制代码

将源码编译成机器码

我们以一段 C 代码为例,来看一下代码被编译成二进制可执行程序之后,是如何被 CPU 执行的。
在这段代码中,只是做了非常简单的加法操作,将 x 和 y 两个数字相加得到 z,并返回结果 z。
int main()
{
int x = 1;
int y = 2;
int z = x + y;
return z;
}
我们知道,CPU 并不能直接执行这段 C 代码,而是需要对其进行编译,将其转换为二进制的机器码,然后 CPU 才能按照顺序执行编译后的机器码。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了CPU执行程序的过程,从程序编译成二进制机器码,到机器码加载到内存中,再到CPU执行指令的过程进行了详细解析。通过分析C代码编译成机器码的过程,展示了机器码和对应的汇编代码,并解释了汇编语言和机器语言的关系。读者可以通过观察编译生成的机器码和汇编代码,了解CPU执行指令的过程,以及程序执行的本质是CPU按顺序执行指令。文章还介绍了CPU中的PC寄存器、通用寄存器以及常用的指令类型,帮助读者理解CPU执行指令的机制。整体而言,本文对于想要深入了解计算机底层工作原理的读者来说是一篇很有价值的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • 王楚然
    1. 二进制代码装载进内存,系统会将第一条指令的地址写入到 PC 寄存器中。 2. 读取指令:根据pc寄存器中地址,读取到第一条指令,并将pc寄存器中内容更新成下一条指令地址。 3. 分析指令:并识别出不同的类型的指令,以及各种获取操作数的方法。 4. 执行指令:由于cpu访问内存花费时间较长,因此cpu内部提供了通用寄存器,用来保存关键变量,临时数据等。指令包括加载指令,存储指令,更新指令,跳转指令。如果涉及加减运算,会额外让ALU进行运算。 5. 指令完成后,通过pc寄存器取出下一条指令地址,并更新pc寄存器中内容,再重复以上步骤。

    作者回复: 没问题

    2020-04-07
    40
  • ChaoZzz
    不理解为什么要 movl $0, -4(%rbp) 把 0 写进栈帧

    作者回复: 这个我也没搞懂,我继续找专家请教哈,有结果我会第一时间回复

    2020-04-09
    7
    10
  • OnE
    “movl $0, -4(%rbp)”这条指令并不是“在栈中把返回值默认设置为0”,一般情况下函数不是通过eax来返回值?那为什么还要多此一举呢?感觉这一条指令的存在像是编译器的默认做法,可能是出于安全考虑。

    作者回复: 你说的对,这个的确不是返回值,我特地问了几个精通汇编的朋友,为什么要在栈中放个0他们也没有给出准确答案。 接下里,我继续查找下这个问题的答案!

    2020-04-07
    3
    5
  • 亦枫丶
    “现在 x+y 的结果保存在了 eax 中了,接下来 CPU 会将结果保存中内存中” ,老师这里的内存是不是应该是寄存器呀,还是说这个结果确实写到了内存?

    作者回复: 这个没有问题,因为编译这个程序的时候,我使用了 gcc -O0 -o code_prog code.c 其中了-O0 选项是指编译器不会对编译的文件做任何优化操作,这是为了讲解方便,所以你觉得中间很繁琐多余的操作; 如果你编译时,将优化选项开启了,那么编译后的机器代码会和没有优化过的机器代码会存在着巨大的差异。 比如返回值在eax中了,然后调用movl %eax, -16(%rbp) 将eax中的值写到栈帧(rbp)偏移了16个单位的地方!

    2020-04-08
    1
  • Prof.Bramble
    老师,我想问问关于全局执行上下文,如果它是存放在堆中的,那全局变量里面的基础类型的值,也在堆中吗?还是基础类型的值依然通过某种映射保存在栈中? 我个人更希望理解成是在堆中,主要产生这个问题的原因是我好奇全局变量的声明数量是否会影响栈空间的容量,还是说栈中保存的全局执行上下文只是一个指向栈存储位置的指针?
    2021-04-03
    2
    3
  • 神仙朱
    更新地址到pc寄存器,好像是存指令开头的地址,怎么知道这条指令到哪里结束,也就是结尾地址呢
    2020-08-17
    1
    1
  • Crystal
    关于内存寄存器推荐《汇编语言》 王爽,入门级教程,很受用
    2022-02-10
  • 馒头爱学习
    上大学的时候,觉得学习汇编没什么用处,现在终于找到用武之地了,感谢老师!
    2022-01-12
  • Geek_bb5943
    到这里留言的人比较少,我也来聊聊吧。代码到二进制代码,经过ast语法解析,再到字节码,在到机器码,也就是二进制代码,二进制代码会被写入内存,被写入到pc寄存器,后面通过读取寄存器里的指令并分析执行,就可以啦!不知道理解有没有错
    2020-08-11
  • 灰的更高
    老师,我对于指令存储的内存地址的想法,您看是否正确。因为文中指令间的内存地址以字节为单位,相差四个字节,就表示系统或汇编器为32位,32位的十六进制地址应该是8位,若以字节为单位,也就变成9位地址,是否可以这样理解?
    2020-05-12
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部