• ack
    2019-05-29
    opcode(6位)
        000000 10001 10010 01000 00000 100000
        =0000 0010 0011 0010 0100 0000 0010 0000(对应纵向打孔带)
        =0X02324020
     3
     47
  • lzhao
    2019-05-03
    机器码不是二进制吗?为什么gcc把汇编编译成16进制?

    作者回复: l'hao同学你好,是二进制,16进制只是为了显示方便,毕竟一串0和1在显示上太没有效率了

    
     22
  • 郭江伟
    2019-05-22
    gjw@gjw:~/csapp/000$ cat simplest.c
    int main(){
    int a=1,b=20;
    int c=a+b;
    }
    生成的汇编及其具体解释:
    push %rbp 压栈 ,基址指针
    mov %rsp,%rbp 将堆栈寄存器内容移动到基址寄存器
    movl $0x1,-0xc(%rbp) 将栈基地址偏移12字节设为1,对应变量a=1
    movl $0x14,-0x8(%rbp) 将栈基地址偏移8个字节设为20(16进制14=10进制20),变量b=20
    mov -0xc(%rbp),%edx 将栈基地址偏移12字节的数据移动到edx寄存器
    mov -0x8(%rbp),%eax 将栈基地址偏移8个字节的数据移动到eax寄存器
    add %edx,%eax edx 数据和eax数据相加,结果保存到eax寄存器
    mov $0x0,%eax 重置eax寄存器
    pop %rbp 弹出栈数据
    retq main函数返回并退出
    展开
     1
     19
  • 老妖
    2019-05-12
    老师请教个问题,

    像python这种解释型的语言,需要一行行地编译,那它就不能综合所有的源文件来考虑了,像什么重定向这些怎么实现?或者跳转到某个地址,怎么实现,我担心的是一行一行的解释,看不到程序的全貌,怎么知道我要跳到哪个地址?

    谢谢!
    展开
    
     11
  • 梨子🍐
    2019-05-03
    没有理解 `0X02324020` 是如何计算出来的?

    作者回复: 梨子同学你好,你把把上一行的二进制,四位四位一读,每四位当成是一个16进制数,就会得到这个结果

     2
     11
  • 冰激凌的眼泪
    2019-05-12
    打孔卡要纵向读,建议Opcode补足6个0,这样好和打孔卡对照
    汇编是不是可以看做机器码的助记符?
     1
     8
  • Ant
    2019-05-10
    最后的卡片 02324020 ,为啥不是从最底下或最上面开始, 为啥3 打了俩孔, 为啥4 又 往上了一行

    作者回复: 顺序是根据用什么样的机器读取来的,我们这里假设就是从左往右一列一列读取的。

    一列卡片代表一个数,白色代表没有打孔,黑色代表打孔。3换算成二进制就是 0011,也就是上面两个不打孔,下面两个打孔,4就换算成 0100,也就是第二个打孔,其他的不打孔

     1
     7
  • 程斌
    2019-06-15
    老师你好,通篇看下来,有一个地方没有怎么懂得。
    “对应的 MIPS 指令里 opcode 是 0,rs 代表第一个寄存器s1的地址是17,rt代表第二个寄存器s2的地址是18,rd代表目标的临时寄存器t0的地址,是8.”
     3
     6
  • coder
    2019-05-05
    老师您好,说到指令,让我想起来困惑我本科时期很久的一个问题:

    用C或者其他的高级语言可以实现更多的语言,那么这么一直追问下去,就有个类似蛋生鸡的问题,第一个编程语言是怎么来的?

    编程语言一般会有"自举"的功能,那么自举是怎么实现的?比如说Go语言就是自己实现自己,那么在没有Go编译器的基础上,怎么做到自己编译自己的?

    作者回复: json同学你好,第一台计算机ENIAC,如果你去计算机历史博物馆看一下真机就会明白,他的各种输入都是一些旋钮,可以认为是类似用机器码在编程,后来才有了汇编、C这样越来越高级的语言。

    编程语言是自举的,并不需要第一个编译器就是用自己这个语言来写的。通常是先有了别的语言写好的编译器,然后再用自己来写自己语言的编译器。

    更详细的关于鸡蛋问题,可以直接看Wikipedia上,讲了多种这个问题的解决方案
    https://en.wikipedia.org/wiki/Bootstrapping_(compilers)

    
     6
  • 二星球
    2019-05-04
    老师您好,我想问一个问题,C语言>汇编语言>机器语言 一般是这样的编译顺序,为什么不是 C语言>机器语言 一步到位这样编译呢?

    作者回复: 杨怀同学你好,其实有一步到位的,就是两个步骤都通过一个命令先后执行,顺序完成,gcc现在就可以一个命令直接变成可执行的binary。

    只是为了方便debug,你可以认为通过机器语言我们也可以反推出汇编语言长什么样子。

    
     6
  • 周曙光爱学习
    2019-05-09
    指令和机器码的关系是?可以理解为cpu指令类似数学公式,我们写的程序在套用这些公式,然后公式+参数生成机器码?

    作者回复: 👍,周曙光爱学习同学你好,这个理解和比喻很形象

    
     5
  • 一步
    2019-05-04
    我们说过,不同的 CPU 有不同的指令集,也就对应着不同的汇编语言和机器码 这句话中,在不同的指令集中 汇编语言和机器码 的关系是怎么对应的呢? 还有一个问题就是在高级语言转换为机器码的时候 是不是要读取CPU的具体的型号呢? 然后在转换为 对应CPU型号的机器码。 如果是,那么物理机器是不是要维护一个很大的对应关系表???

    作者回复: 一步同学你好,

    不同指令集里,对应的汇编代码会对应这个指令集的机器码呀。

    大家不要把“汇编语言”当成是像C一样的一门统一编程语言。

    “汇编语言”其实可以理解成“机器码”的一种别名或者书写方式,不同的指令集和体系结构的机器会有不同的“机器码”

    高级语言在转换成为机器码的时候,是通过编译器进行的,需要编译器指定编译成哪种汇编/机器码。

    物理机自己执行的时候只有机器码,并不认识汇编代码。

    编译器如果支持编译成不同的体系结构的汇编/机器码,就要维护很多不同的对应关系表,但是这个表并不会太大。以最复杂的Intel X86的指令集为例,也只有2000条不同的指令而已。

    
     4
  • Geek_guo
    2019-05-04
    希望老师可以把指令执行后的整个过程在分析下,不然现在还是不理解这个指令对于一条加法有什么作用

    作者回复: Geek_guo同学你好,加法在电路层面怎么执行,我们会在加法器里面讲解。

    我们的指令运行,怎么和ALU这样的算术逻辑单元串联起来,我们会在CPU里面讲解,尽请期待啊。

    
     3
  • ginger
    2019-05-24
    看到指令,联想到上一讲的cpu性能和指令数的关系,这里想提问下:
    是否可以通过将指令更加细分(功能上的细分,比如指令ab完成a+b,指令abc完成a+b+c)
    来实现一个高级语言本身需要对应到10条指令时候,变成了只需要对应7条指令的效果,

    我想这个一定是可行的,但应该没什么意义,因为cpu的指令集,发展了这么多年了,应该也是没有优化的空间了吧.

    作者回复: 可以的,这个就是历史上的CISC和RISC的争论。

    其实指令集都在不断更新微调。而体系结构最近RISC-V又火起来了。

    因为纯粹靠提升频率硬件的方法已经没有什么空间了,所以其实又进入了优化指令集乃至整个体系结构的阶段了。

    
     2
  • Sharongo
    2019-05-20
    计算机小白想问一个很蠢的问题:为什么CPU不能放着所有指令,为什么要区分cpu和内存以及其它硬件不可以把功能都放在一个器件上吗?

    作者回复: Sharongo同学你好,

    因为放不下啊,也放不起啊,而且这样怎么做到前面讲的“可编程”和“可存储”呢?

     1
     2
  • 子杨
    2019-05-18
    徐老师,每一条计算机指令由 CPU 执行的时候,实际上是不是都是电路的连通或关闭?

    作者回复: 是啊,我们在讲解CPU的时候,你可以从电路的角度来理解指令是怎么在硬件层面执行的。

    
     2
  • Nevermore
    2019-05-12
    老师shell脚本是一步编译成机器码的吗?还是转换成汇编再编译成机器码

    作者回复: 如果在这个映射关系里面,可以认为shell脚本是被bash解释器来运行的,调用对应的编译好的二进制可执行文件相当于bash解释器在做对应的“翻译”动作

    
     2
  • 给你力量
    2019-05-08
    1. 老师我对汇编语言的意义还是不太理解,是不是可以将汇编语言的意义理解为对机器码的封装,提高对于程序员的可阅读性呢?
        就是所有的代码,都可以归纳为一组特定组合的机器码操作,可以直接将高级语言代码编译为机器码执行,但是这样子的话,程序员就无法看出这行代码到底进行了什么操作。
        如果把特定作用的机器码封装为汇编代码,高级语言先编译成可读性高的汇编代码,这样就能理解代码实际执行了什么机器码操作。
         所以汇编语言是基于机器语言的基础上生成的。

         不知道我这个理解对不对,希望老师能指点一下。

    2. 如何区分R、I、J指令,是通过opcode吗?如果是的话,是不是就三种opcode?

    谢谢老师的分享!
    展开

    作者回复: 给你力量同学你好,

    1. 你的理解是对的。不过其实历史上汇编不只是为了让程序员可以更容易读代码,也是为了让程序员更容易写代码。毕竟无论是打孔带,旋钮还是其他的更“古老”的方式来编程都太没有效率了。

    2. 是的,应该说是三大类opcode,每一类里面有很多不同的具体的opcode。

    
     2
  • Kelly.W
    2019-05-04
    老师您好,课程里说汇编代码和机器码是一一对应的,我现在知道在不同平台的机器码是不一样的(linux/windows),那么不同平台也有不同的高级语言->汇编代码的对应规则吗?

    作者回复: 机器码的差异不在于操作系统(也就是不在于Linux/Windows)。而是在于体系结构(Intel X86/ARM/MIPS)。
    不同平台的汇编语言也是不同的,所以同样的高级语言编译器在不同的平台上编译出来的代码也是不一样的。

     2
     2
  • 发条橙子 。
    2019-05-04
    刷了两遍大致清晰了 ,又学到不少知识 , 看完感觉从高级语言-到汇编-机器码的转换实际上不是很复杂 ,重要的是刻纸袋是个体力活 。

    老师, 这边还有两个细节点想请教一下:
    1. 前面的文章讲冯诺依曼体系结构的时候说到 。 运算器、控制器、存储器、输入输出设备 , 这里将Cpu指令集存储在存储器 , 这里的存储器指的是硬盘么 ?
    2. 汇编语言和Cpu指令集先后的问题 , 老师上面 add 的例子是从 汇编 推导出 MIPS 对应的二进制 Cpu指令 。 按照历史发展 ,是MIPS公司先推出了一款自己的CPU指令集, 然后对应的汇编语言厂商在按照这个指令集开发相应的汇编语言么 ?

    希望老师能指点一二 ,另外老师五一节快乐 (虽然快过完了)
    展开

    作者回复: 发条橙子同学你好,也希望你过了一个愉快的五一啊。

    CPU的“指令集”是一个抽象的概念,你可以认为实际是被变成了CPU的电路。

    我们具体的一个个程序的指令,是存在内存里的,或者说,是程序用一个文件格式存在磁盘上,然后通过装载器加载到内存里面,再一条条加载到指令寄存器里面,然后执行的。

    关于汇编语言,你可以这样认为,不过厂商一般会直接提供对应的汇编语言和汇编器,但是也的确有支持多种指令集的第三方汇编语言和汇编器。

    
     2
我们在线,来聊聊吧