[TOC]
## 環境準備
### 虛擬機
這里我使用的虛擬機是:[virtualbox](https://www.virtualbox.org/wiki/Downloads)

### 鏡像
鏡像使用的[Ubuntu 20.04.2.0 LTS](http://releases.ubuntu.com/20.04/)

關于virtualbox環境設置沒什么說的,網絡記得啟用并且使用橋接模式即可

### 安裝gcc,vim,git
這個就很簡單了三條命令
`sudo apt-get update`
`sudo apt-get install gcc`
`sudo apt-get install vim`
`sudo apt-get install git`
## 開始編碼
### HelloWord
還是從C語言最開始的HelloWorld開始
```c
#include "stdio.h"
int main(int argc, char const *argv[])
{
printf("Hello World!\n");
return 0;
}
```

### 程序編碼過程
使用gcc編譯這段代碼
`gcc HelloWorld.c -o HelloWorld`
然后執行發現執行成功

gcc -o 只是完成編譯工作的驅動程序,它會根據編譯流程分別調用**預處理程序**、**編譯程序**、**匯編程序**、**鏈接程序**來完成具體工作。
接下來對比著圖片按照每一個步驟編譯一下這個程序來提升一下對這個過程的理解:

#### 源文件生成預處理文件,加入頭文件,替換宏。
`gcc -E HelloWorld.c -o HelloWorld.i `
#### 預處理文件生成編譯文件
`gcc -S HelloWorld.i -o HelloWorld.s `
#### 編譯文件生成匯編文件:
`gcc -c HelloWorld.s -o HelloWorld.o `
#### 匯編文件生成可執行文件:
`gcc HelloWorld.o -o HelloWorld `
#### 源文件生成可執行文件:
`gcc HelloWorld.c -o HelloWorld `
#### Linux系統運行可執行文件:
`./HelloWorld`
### 程序裝載執行
在講到這里的時候彭東老師提到了圖靈機和馮諾依曼,這里我把中專欄的圖片貼出來,我感覺這兩個概念只要理解即可,所以不做深入學習,理解即可,他們只是計算機形成過程中的幾個基礎理論或者說必要條件。
### 更形象地將 HelloWorld 程序裝入原型計算機
#### 反匯編特定指令機器碼
使用**objdump**從objfile中反匯編那些特定指令機器碼的section
`objdump -d HelloWorld`

第一列為地址;
第二列為十六進制,表示真正裝入機器中的代碼數據;
第三列是對應的匯編代碼;
第四列是相關代碼的注釋。這是 x86_64 體系的代碼,由此可以看出 x86 CPU 是變長指令集。
#### 將代碼裝入上面圖靈機+馮諾依曼體系結構

#### 以上知識涉及到知識盲區查閱的資料
##### 匯編中的棧幀理解
###### 基本概念
引用百度百科的介紹:C語言中,每個棧幀對應著一個未運行完的函數。棧幀中保存了該函數的返回地址和局部變量。棧幀也叫過程[活動記錄](https://baike.baidu.com/item/%E6%B4%BB%E5%8A%A8%E8%AE%B0%E5%BD%95),是[編譯器](https://baike.baidu.com/item/%E7%BC%96%E8%AF%91%E5%99%A8)用來實現過程/[函數調用](https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8)的一種數據結構。可以理解為:棧幀就是存儲在用戶棧上的(當然內核棧同樣適用)每一次函數調用涉及的相關信息的記錄單元。
###### 分析棧幀的記錄活動
簡單用c寫個函數調用的demo

使用objdump命令反匯編看一下

> x86\_64通用寄存器
> %rax 通常用于存儲函數調用的返回結果,同時也用于乘法和除法指令中。
> %rsp 是堆棧指針寄存器,通常會指向棧頂位置
> %rbp 是棧幀指針寄存器,用于標識當前棧幀的起始位置
> %rdi,%rsi,%rdx,%rcx,%r8,%r9 用來傳遞函數參數,依次對應第1參數,第2參數至第6參數
> %rbx,%r12,%r13,%14,%15 ,%r10,%r11 用作數據存儲,屬于通用性更為廣泛的寄存器,編譯器或匯編程序可以根據需要存儲任何數據。

## 課后思考題
為了實現 C 語言中函數的調用和返回功能,CPU 實現了函數調用和返回指令,即上圖匯編代碼中的“call”,“ret”指令,請你思考一下:call 和 ret 指令在邏輯上執行的操作是怎樣的呢?
經過上面的代碼分析,已經可以解決這個問題了,下面附一些精彩留言以供參考。
> 針對第一個問題,在gcc編譯完成之后,函數對應的指令序列所在的位置就已經確定了,因此這是編譯階段需要考慮的問題 。
> 至于第二個問題,在執行完call指令的同時,需要將call指令下面一條指令的地址保存到棧內存中,同時更新%rsp寄存器指向的位置,然后就可以開始執行被調函數的指令序列,執行完畢后,由ret指令從rsp中獲取棧頂的returnadress地址,然后跳轉到call的下一條指令繼續執行
>call和ret其實是一對相反指令,調用call時會將當前IP入棧,即push IP,然后執行跳轉即jmp,而ret也是將棧中的IP推出寫入IP寄存器,即pop IP。
- 微服務
- 服務器相關
- 操作系統
- 極客時間操作系統實戰筆記
- 01 程序的運行過程:從代碼到機器運行
- 02 幾行匯編幾行C:實現一個最簡單的內核
- 03 黑盒之中有什么:內核結構與設計
- Rust
- 入門:Rust開發一個簡單的web服務器
- Rust的引用和租借
- 函數與函數指針
- Rust中如何面向對象編程
- 構建單線程web服務器
- 在服務器中增加線程池提高吞吐
- Java
- 并發編程
- 并發基礎
- 1.創建并啟動線程
- 2.java線程生命周期以及start源碼剖析
- 3.采用多線程模擬銀行排隊叫號
- 4.Runnable接口存在的必要性
- 5.策略模式在Thread和Runnable中的應用分析
- 6.Daemon線程的創建以及使用場景分析
- 7.線程ID,優先級
- 8.Thread的join方法
- 9.Thread中斷Interrupt方法學習&采用優雅的方式結束線程生命周期
- 10.編寫ThreadService實現暴力結束線程
- 11.線程同步問題以及synchronized的引入
- 12.同步代碼塊以及同步方法之間的區別和關系
- 13.通過實驗分析This鎖和Class鎖的存在
- 14.多線程死鎖分析以及案例介紹
- 15.線程間通信快速入門,使用wait和notify進行線程間的數據通信
- 16.多Product多Consumer之間的通訊導致出現程序假死的原因分析
- 17.使用notifyAll完善多線程下的生產者消費者模型
- 18.wait和sleep的本質區別
- 19.完善數據采集程序
- 20.如何實現一個自己的顯式鎖Lock
- 21.addShutdownHook給你的程序注入鉤子
- 22.如何捕獲線程運行期間的異常
- 23.ThreadGroup API介紹
- 24.線程池原理與自定義線程池一
- 25.給線程池增加拒絕策略以及停止方法
- 26.給線程池增加自動擴充,閑時自動回收線程的功能
- JVM
- C&C++
- GDB調試工具筆記
- C&C++基礎
- 一個例子理解C語言數據類型的本質
- 字節順序-大小端模式
- Php
- Php源碼閱讀筆記
- Swoole相關
- Swoole基礎
- php的五種運行模式
- FPM模式的生命周期
- OSI網絡七層圖片速查
- IP/TCP/UPD/HTTP
- swoole源代碼編譯安裝
- 安全相關
- MySql
- Mysql基礎
- 1.事務與鎖
- 2.事務隔離級別與IO的關系
- 3.mysql鎖機制與結構
- 4.mysql結構與sql執行
- 5.mysql物理文件
- 6.mysql性能問題
- Docker&K8s
- Docker安裝java8
- Redis
- 分布式部署相關
- Redis的主從復制
- Redis的哨兵
- redis-Cluster分區方案&應用場景
- redis-Cluster哈希虛擬槽&簡單搭建
- redis-Cluster redis-trib.rb 搭建&原理
- redis-Cluster集群的伸縮調優
- 源碼閱讀筆記
- Mq
- ELK
- ElasticSearch
- Logstash
- Kibana
- 一些好玩的東西
- 一次折騰了幾天的大華攝像頭調試經歷
- 搬磚實用代碼
- python讀取excel拼接sql
- mysql大批量插入數據四種方法
- composer好用的鏡像源
- ab
- 環境搭建與配置
- face_recognition本地調試筆記
- 虛擬機配置靜態ip
- Centos7 Init Shell
- 發布自己的Composer包
- git推送一直失敗怎么辦
- Beyond Compare過期解決辦法
- 我的Navicat for Mysql
- 小錯誤解決辦法
- CLoin報錯CreateProcess error=216
- mysql error You must reset your password using ALTER USER statement before executing this statement.
- VM無法連接到虛擬機
- Jetbrains相關
- IntelliJ IDEA 筆記
- CLoin的配置與使用
- PhpStormDocker環境下配置Xdebug
- PhpStorm advanced metadata
- PhpStorm PHP_CodeSniffer