用汇编的思想理解C/C++

时间:2021-02-18 01:08:00

最近面试找工作, 遇到一个美团一个很好的面试官。 虽然面试结果可能不尽如意, 但是面试官给出的意见确非常中肯。 所以觉得有必要重新学习一下基础。 就从操作系统开始学起。刚好之前从git上发现有人共享了一本30天自制操作系统。 书的标题虽然有点夸张, 但是觉得还是觉得跟着一步一步写,效果会比单纯的看长篇大论的理论要好。 也放出github的地址, 有兴趣的也可以下下来看看。

30天自制操作系统

一切皆01

CPU本质上所有的运算无非是通过与非门对0和1进行一系列的运算。cpu通过总线(地址总线:负责对内存进行寻址 ;控制总线: 对外设设备的控制(包括:键盘,鼠标等);数据总线:将数据传送到内存;)将外部的0 1信号加载到cpu内部的寄存器中, cpu直接对寄存器中的01进行操作, 然后将运算后的数据或是传给外设; 或是返回内存的某个地址; 或是将数据写入到内存中。

说了半天等于没说,不管学软件还是硬件的人都知道的道理。没错,大道理都会懂,但是具体到语言级别, 是怎么转化为01的这些可能就要深入分析了; 从汇编的角度理解还是比较不错的方向。

还是先从最简单的打印hello world的角度开始:

printf("hello, world!");

翻译成汇编,大致的结构可能是这样:

; 汇编中用分号表示注释
; 当C语言执行到printf函数时, 大概对应的汇编会有:
; INT xxx
; JMP Printf

printf:     ; printf这里可以理解为一个标签,其实也是一个地址,cpu执行这个函数,就是跳到一个地址
    mov AX, "hello, world"    ; 这条语句这种写法不对,明白大概意思就行了, 意思大概就是将hello, world的二进制赋值给cpu的寄存器

    mov [BX], AX           ; [BX]对应的可能是屏幕的地址, 这里的大概意思是说把AX(hello, world)输出到屏幕

数组声明:

char a[3];

对应的汇编:

a:
    DB 0x000x000x00    ;当然C语言 

数组赋值:

char a[3] = {0x01, 0x02, 0x03};

对应的汇编:
首先a是一个指针, 其实就是指向内存的一个地址, 我们假设现在AX存放的是该地址

mov [AX], 0x01 ; [AX] 表示地址对应的内存, 就是把 0x01 放入指针a指向的内存 
ADD AX, 1      ; 对指针加1
mov [AX], 2    
ADD AX, 1
mov [AX], 3     ; 每一步的赋值mov都会额外占用一些空间

static:

static char a[3] = {0x01, 0x02, 0x03};

翻译成汇编:

a:
     DB 0x01 0x02, 0x03 ; 相比普通的赋值,占用的内存要少, 而且每次能保持变量内容的持久。

–未完,待续–

以上只是自己个人粗浅的理解, 很多方面可能有误,欢迎大神指出。