课前热身|学习这门课前,你需要了解哪些知识?

2021-12-06 于航
《深入 C 语言和程序运行原理》
课程介绍


讲述:于航

时长:大小10.86M


你好,我是于航。
在我们正式进入到 C 语言课程的学习之前,为了帮助你更好地理解课程内容,我为你准备了一节基础知识讲解课。这是一节选学课,你可以根据自己的实际情况选择性学习。
在这一讲中,我会用通俗易懂的方式,为你介绍这门课中最常用的一些基础知识,分别是常见数据量单位、汇编语言,以及 CPU 指令集中涉及的不同类型的寄存器。如果你对这些内容还不太熟悉,那么通过这一讲,你可以对它们有一个大致的印象。我们后面的课程还会提到汇编指令或寄存器,我会视情况进行更加具体的讲解,帮你加深理解。

数据量单位:位、字节和字

位(bit)是计算机中最小的存储单位,每一个位可以存储一个二进制码值的 0 或 1。而字节(byte)则通常是由八个位组成的一个存储单元。在计算机中,字节是最小的可寻址单位,这意味着 CPU 在使用数据时,可以以字节为单位,为每一字节内存分配一个相应的独立地址。
位和字节是在我们的日常工作中最为常见的两个数据量概念,你应该很熟悉。不过,字(word)的概念就没有这么清晰了。字的大小并不固定,一个字的大小可能是 2...

展开全文
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。

精选留言

  • ZR2021
    置顶
    2021-12-07
    于老师,为啥main函数里的asm("movl $0x1, %eax");是将1给eax的,src 跟dst反过来了好像

    作者回复: 这又是一个好问题!其实这里我们在代码中使用的是 AT&T 的写法,是一种默认被编译器广泛支持的内联汇编写法。当然,我们也可以做适当的调整来使用 Intel 写法,比如这样: #include <stdio.h> int main(void) { register long num asm("rax") = 0x100000000; asm( ".intel_syntax noprefix \n\t" "mov eax, 1\n\t" // "mov ax, 1\n\t" ".att_syntax" ); printf("%ld\n", num); return 0; } 但这种方式的问题在于,对于某些汇编器可能没有很好的兼容性。

    共 2 条评论
    22
  • 继业(Adrian)
    2021-12-12
    quizz: ``` mov eax, 0x1 # 0b1 inc eax # 0b10 sub eax, 10 # 0b10 - 0b1010 = 0xfffffff8 xor eax, eax # 0xfffffff8 xor 0xfffffff8 = 0x00000000 add eax, 1 # 0x00000001 mul eax # 0x00000001 mul 0x00000001 = 0x00000001 ``` answer: 0x00000001 = 1

    作者回复: 完全正确!

    
    19
  • 糊糊
    2021-12-07
    请教老师, 文中 mov ebx, 1 ,它所对应的机器指令代码为二进制值 bb 01 00 00 00 ,问题有两个: 1、汇编助记符 mov 是如何被翻译为二进制的 ? 是通过在哪里查的表吗 ,如果是查的表,那表又存在哪里呢 2、 那根据机器码二进制能否推导出汇编代码呢?bb 01 00 00 00 ==》mov ebx, 1

    作者回复: 很好的问题! 第一个问题:每一个汇编指令都有其对应的组成结构,汇编器会根据助记符的名称进行相应的转换。具体的转换细节可以参考官方手册。比如对于 x86-64:https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html 第二个问题:二进制状态下的机器指令识别可以通过每个指令对应的 OpCode 字节进行切分,然后再根据相应的结构解析出整体指令的结构。

    共 3 条评论
    6
  • 权
    2021-12-06
    验证重写64位寄存器低32位/低16位/低8位的代码中如果不是按照文中那样给寄存器赋值,而是任意赋值,建议大家将printf("%ld\n", num);改为printf("%lx\n", num);,输出16进制数,这样才能观察到正确的结果,否则输出10进制数,一开始没注意的话会发现结果很奇怪 思考题: xor eax, eax是异或,eax自己与自己异或应该为0 add eax, 1,相当于0x0+0x1=0x1 mul eax之后eax的结果应该还是0x1,不知道理论分析是否正确,汇编还不是很熟

    作者回复: 答案是正确的哈!

    
    5
  • jack123
    2021-12-07
    xor eax,eax 相当于把eax置零了,最后+1,然后mul相乘 默认与eax相乘,最后还是为1

    作者回复: 没错!

    
    4
  • cc
    2021-12-08
    在 x86-64 架构下,CPU 指令集架构(ISA)中一共定义了 16 个通用目的寄存器,这些寄存器最大可以存放 4 个字,即 64 位长的数据。在汇编代码中 ---- x86-64 下一个字长不就 64bit 了吗,为什么这里说 「4 个字,即 64 位长的数据」

    作者回复: 这是一个很好的发现!我们修改了文章,稍后会更新。 简单来讲就是:字这个概念会在多个地方的多种不同场景下使用。而文中我们介绍的字实际上是指可以体现 CPU 硬件特征的那个字,我一般会称它为硬件字。而在 CPU 指令集中,字也被用来作为衡量数据大小的单位。x86 架构由于历史原因,会将指令集中出现的 WORD 定义为固定 16 位的大小。所以实际文中提到的 4 个字你可以理解为指令字,它的单位是 WORD,4 个字即对应 64 位大小。

    
    3
  • dog_brother
    2021-12-07
    按老师的程序去执行,第一种(asm("movl $0x1, %eax");)结果是1,第二种(asm("movw $0x1, %ax");)结果是4294967297。 ============================== ```c #include <stdio.h> int main(void) { register long num asm("rax") = 0x100000000; asm("movl $0x1, %eax"); // 第一种 // asm("movw $0x1, %ax"); // 第二种 printf("%d\n", num); printf("%ld\n", num); printf("%X\n", num); return 0; } ``` 按我这段的代码去执行,第一种(movl)和第二种(movw)的执行结果都是 ```shell 1 2 2 ```
    展开

    作者回复: 关于这个问题我可以先给点提示,然后你再思考下看看。第一个提示就是把第一行 printf 中的 “%d” 改成 “%ld” 就可以输出正确的结果;第二个提示是 printf 的调用会影响寄存器 rax 的值。

    
    3
  • 琥珀·
    2021-12-13
    因为我的环境有 warning: overflow in conversion from 'long long int' to 'long int' 的告警,所以把 register long num 改成了 register long long num #include <stdio.h> int main(void) { register long long num asm("rax") = 0x100000000; asm("movl $0x1, %eax"); // asm("movw $0x1, %ax"); printf("%llx\n", num); return 0; } 不知道这样理解对不对: 当某个指令需要重写寄存器的低 16 位或低 8 位数据时,寄存器中其他位上的数据不会被修改。所以asm("movw $0x1, %ax") 不会修改rax的值,这时num输出的值为0x100000001 而当指令需要重写寄存器低 32 位的数据时,高 32 位的数据会被同时复位,即置零。所以 asm("movl $0x1, %eax") 会将 rax 的结果置零后再写入1,这时num输出的值为0x1。
    展开

    作者回复: 理解正确哈!

    
    2
  • 墨
    2021-12-12
    eax = 1 eax = eax + 1 eax = eax - 10 异或操作令 eax = 0 eax = eax + 1 eax = eax * eax 最后eax = 1

    作者回复: 正解!

    
    2
  • 傻猫周大福
    2021-12-11
    在clang下,rax寄存器虽然被置位,但在此之前会将rax寄存器的值拷贝到栈中,在输出时不会把被置位后的rax输出,而是从栈中重新取出num的值

    作者回复: 这是一个很好的发现!

    共 3 条评论
    2