寫在前面的話:此系列文章為筆者學(xué)習(xí)CSAPP時的個人筆記,分享出來與大家學(xué)習(xí)交流,目錄大體與《深入理解計(jì)算機(jī)系統(tǒng)》書本一致。因是初次預(yù)習(xí)時寫的筆記,在復(fù)習(xí)回看時發(fā)現(xiàn)部分內(nèi)容存在一些小問題,因時間緊張來不及再次整理總結(jié),希望讀者理解。
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第3章 程序的機(jī)器級表示 - 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第5章 優(yōu)化程序性能 - 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第6章 存儲器層次結(jié)構(gòu) - 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第7章 鏈接- 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第8章 異??刂屏?- 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第9章虛擬內(nèi)存 - 學(xué)習(xí)筆記_友人帳_的博客-CSDN博客
第三章 程序的機(jī)器級表示
1. 代碼編譯過程
gcc -Og -o hello source1.c source2.c ...
gcc -Og -S -fno-if-conversion source.c // 優(yōu)化等級低,便于理解
注:①-Og
為代碼優(yōu)化等級;②-o
表示生成可執(zhí)行文件,-s
可以生成匯編代碼;③生成實(shí)際可執(zhí)行的代碼需要對一組目標(biāo)代碼文件運(yùn)行鏈接器,而這一組目標(biāo)代碼文件中必須含有一個main函數(shù);④有時會在末尾(return后)有90 nop
指令,目的是為了使函數(shù)代碼變?yōu)?6字節(jié),使得存儲器能更好地放置下一個代碼塊,提高性能。
源代碼轉(zhuǎn)化為可執(zhí)行代碼:
①C預(yù)處理器:擴(kuò)展源代碼,插入所有用#include命令指定的文件,并擴(kuò)展所有#define聲明指定的宏;
②編譯器:生成源文件的匯編代碼,后綴.s;
③匯編器:將匯編代碼轉(zhuǎn)化為二進(jìn)制目標(biāo)代碼文件,后綴.o;
④鏈接器:將目標(biāo)代碼文件與實(shí)現(xiàn)庫函數(shù)的代碼合并,填入全局值的地址,生成可執(zhí)行代碼文件。
GDB調(diào)試指令
2. 反匯編
反匯編:將可執(zhí)行二進(jìn)制文件翻譯為匯編語言
objdump -d target.o
objdump -S target.o > target.txt (在反匯編中加入C代碼,且重定向輸出到target.txt)
cat target.txt 查看
3. 匯編相關(guān)(AT&T格式)
3.1 偽指令
所有以.
開頭的指令都是指導(dǎo)匯編器和鏈接器工作的偽指令;
3.2 匯編代碼后綴
3.3 寄存器
(1)通用寄存器:
規(guī)則:生成1字節(jié)和2字節(jié)數(shù)字的指令會保持剩下的字節(jié)不變;生成4字節(jié)數(shù)字的指令會把高位4個字節(jié)置為0。
(2)段寄存器:
(3)指令指針寄存器EIP/PC
(4)EFLAGS寄存器
(5)系統(tǒng)寄存器
(6)浮點(diǎn)單元FPU
3.4 操作數(shù)指示符
操作數(shù)類型:
①立即數(shù):用$
符號表示,代表常數(shù)值;
②寄存器:直接訪問寄存器的值;
③內(nèi)存尋址: I m m ( R b , R i , S ) = I m m + R b + R i ? S Imm(R_b,R_i,S)=Imm+R_b+R_i*S Imm(Rb?,Ri?,S)=Imm+Rb?+Ri??S,其中, I m m Imm Imm表示立即數(shù)偏移, R b R_b Rb?表示基址寄存器, R i R_i Ri?表示變址寄存器, S S S為比例因子,僅能取值1,2,4,8。計(jì)算得到的為一個地址,相當(dāng)于解引用操作。
3.5 mov指令
注意:
①兩個操作數(shù)不能同時指向內(nèi)存位置。
②寄存器部分的大小必須與指令最后一個字符(‘b’,‘w’,‘l’,‘q’)指定的大小匹配。大多數(shù)情況,MOV指令只會更新目的操作數(shù)指定的寄存器字節(jié)或內(nèi)存位置,但當(dāng)movl指令以寄存器作為目的時,會把該寄存器的高4位設(shè)置為0(任何為寄存器生成32位值的指令都會把該寄存器的高位部分置為0)。
③不要給%rsp賦值(系統(tǒng)保留)。
擴(kuò)展 - 零擴(kuò)展(movz)、符號擴(kuò)展(movs)+大小指示符(源,目的)
條件傳送
cmov
cc
src, dst
cc
表示條件,使用EFLAGS中的條件碼實(shí)現(xiàn)條件判斷對于無符號數(shù),使用a,b,e,b,c分別表示大于、小于、等于、否定、進(jìn)位
對于有符號數(shù),使用g,l,e,n,o分別表示大于、小于、等于、否定、溢出
3.6 棧操作
棧向下增長,棧頂為低地址。
指令:
示意:
3.7 算術(shù)和邏輯操作
注意:
leaq并不是取源S的地址放入寄存器D,而是將有效地址放入,例如若%rdx值為x,則指令leap 7(%rdx, %rdx, x) %rax
將寄存器%rax的值設(shè)置為5x+7
特殊的算數(shù)操作:八字
3.8 調(diào)試常用指令
- 編譯:./mak64 try64
- 調(diào)試:gdb ./try64
- 設(shè)置斷點(diǎn):b _start
- 打開源代碼窗口:layout src
layout split - 上方源代碼,下方匯編
打開寄存器觀察窗口:tui r g r表示register,g表示general,通用寄存器
運(yùn)行:r
在斷點(diǎn)處停止后,單步運(yùn)行:n
4. IA32的內(nèi)存管理
4.1 實(shí)地址模式
實(shí)地址模式:存儲內(nèi)容為真實(shí)物理地址。
內(nèi)存分段:16位地址線不能直接表示20位地址,采用內(nèi)存分段方式,使用兩個16位地址來表示。表示為段地址:段內(nèi)偏移量
;約定段地址低4為為0,便可以用16位地址表示段地址,如此將內(nèi)存空間劃分為64KB的段。而實(shí)際地址可以采用實(shí)際地址 = 段地址0 + 段內(nèi)偏移量
計(jì)算得到(段地址后補(bǔ)
0
16
0_{16}
016?)。
4.2 保護(hù)模式
將段描述符(8字節(jié),段的相關(guān)信息)在段描述符表中的索引值存放在段寄存器(2字節(jié))中。而在段描述符表中的每一行(每一個段描述符),都保存了段的相關(guān)參數(shù)、訪問權(quán)限等信息。
GDT(全局描述符表)和LDT(局部描述符表)都用來存放各種描述符,例如段描述符,但這掩蓋不了它們也是內(nèi)存段的事實(shí)。簡單地講,他們也是段。但是,因?yàn)樗鼈冇糜谙到y(tǒng)管理,故稱為系統(tǒng)的段或者系統(tǒng)段。GDT是唯一的,整個系統(tǒng)中只有一個,所以只需要用GDTR寄存器(CPU中)存放其線性基地址和段界限即可。其中存儲了操作系統(tǒng)使用的代碼段、數(shù)據(jù)段、堆棧段的描述符以及各個程序的LDT段;但LDT不同,每個程序有一個獨(dú)立的LDT,存放了對應(yīng)程序的代碼段、數(shù)據(jù)段、堆棧段的描述符等信息。當(dāng)要使用這些LDT時,可以用它們的選擇子來訪問GDT,將LDT描述符加載到LDTR寄存器。
全局描述符表寄存器GDTR(48位)指向GDT在內(nèi)存中的地址。局部描述符表寄存器LDTR(16位)指向LDT段在GDT中的索引。
在段選擇器(保護(hù)模式下的段寄存器)中:
(1)平坦分段模式
而在段描述符表中:(16進(jìn)制)所有段被映射到32位物理地址空間,程序至少分為代碼段和數(shù)據(jù)段兩個段。
全局描述符表GDT:
基址(32位)指向段的起始地址(圖示中指向0000 0000,很低的地址空間為操作系統(tǒng)所用);
界限指該段的長度,其中,0040是相對值,要在后方加上000(乘以4k),即0040 000
,也說明了段的大小都是4k的倍數(shù)。
(2)多段模式
局部描述符表LDT:
保護(hù)模式下的段尋址總結(jié):
(3)內(nèi)存分頁
5. 控制(條件、循環(huán)、分支)
5.1 條件碼
CF
:進(jìn)位標(biāo)志。最高有效位有進(jìn)位(無符號溢出)置為1,否則置0。
ZF
:零標(biāo)志。最近的操作得出的結(jié)果為0。
SF
:符號標(biāo)志。最近的操作得到的結(jié)果為負(fù)數(shù)。
OF
:溢出標(biāo)志。最近的操作導(dǎo)致一個補(bǔ)碼溢出(正溢出或負(fù)溢出)
除了leaq指令,其余算術(shù)和邏輯操作都伴隨著進(jìn)位標(biāo)志的設(shè)置。
還有一些指令只用于設(shè)置條件嗎而不改變?nèi)魏纹渌拇嫫鳌?/p>
SET指令:可以通過條件碼的組合來進(jìn)行各種條件操作(指令的后綴表示不同的條件而不是操作數(shù)大小)。目的操作數(shù)是低位單字節(jié)寄存器元素之一,或是一個字節(jié)的內(nèi)存位置,指令會將這個字節(jié)設(shè)置為0或1。
cmp指令
cmpq src1, src2
計(jì)算src2-src1的值和0比較,僅用結(jié)果設(shè)置條件碼,而不改變目的操作數(shù)。
test指令
testq src2, src1
根據(jù)src2 & src1 的數(shù)值來設(shè)置條件碼,結(jié)果并不保存,通常將其中一個操作數(shù)看作是一個掩碼。
5.2 跳轉(zhuǎn)指令jump
jump指令會導(dǎo)致執(zhí)行切換到程序中一個全新的位置。在匯編中,這些跳轉(zhuǎn)的目的地通常用一個標(biāo)號(label)指明。
直接跳轉(zhuǎn):jmp .L1 直接跳轉(zhuǎn)到L1標(biāo)號位置
間接跳轉(zhuǎn):jmp *%rax 以%rax中的值作為讀地址,從內(nèi)存中讀出跳轉(zhuǎn)目標(biāo)
注:跳轉(zhuǎn)條件為1表示無條件跳轉(zhuǎn)。
跳轉(zhuǎn)指令的編碼
PC相對跳轉(zhuǎn)
絕對地址跳轉(zhuǎn)
5.3 用條件控制來實(shí)現(xiàn)條件分支
將if轉(zhuǎn)化為goto類型,直接對應(yīng)于匯編。
if-else的通用轉(zhuǎn)換模板
// if-else版本
if (test-expr)
then-statement
else
else-statement
// goto版本
t = test-expr;
if (!t)
goto false;
then-statement
goto done;
false:
else-statement
done:
使用數(shù)據(jù)的條件轉(zhuǎn)移來實(shí)現(xiàn)條件分支的好處:
(將未知的跳轉(zhuǎn)轉(zhuǎn)換為已知的計(jì)算,消除不確定性)
可以使得CPU的流水線中充滿了待執(zhí)行的指令,避免條件預(yù)測邏輯(猜測每條跳轉(zhuǎn)指令是否會執(zhí)行)預(yù)測錯誤而導(dǎo)致浪費(fèi)CPU的時鐘周期,以提高流水線性能。
條件傳送指令:
5.4 循環(huán)
用條件測試和跳轉(zhuǎn)組合起來實(shí)現(xiàn)循環(huán)(do-while、while、for)
// do-while通用形式
do
body-statement
while (test-expr);
// goto形式
loop:
body-statement
t = test-expr;
if (t)
goto loop;
/* ----------------- */
// while 通用形式
while (test-expr)
body-statement
// while goto形式1 - 跳轉(zhuǎn)到中間
goto test;
loop:
body-statement
test:
t = test-expr;
if (t)
goto loop;
// while goto形式2 - guarded-do
// 先翻譯為do-while,再翻譯為goto
t = test-expr;
if (!t)
goto done;
loop:
body-statement
t = test-expr;
if (t)
goto loop;
done:
/* ----------------- */
// for 通用形式
for (init-expr; test-expr; update-expr)
body-statement
// for轉(zhuǎn)化為while
init-expr;
while (test-expr) {
body-statement
update-expr;
}
5.5 switch語句
連續(xù)性較好的switch語句用跳轉(zhuǎn)表,不好的用決策樹(一堆if else)
switch使用跳轉(zhuǎn)表(一個數(shù)組),表項(xiàng) i i i是一個代碼段的地址,這個代碼段實(shí)現(xiàn)當(dāng)switch索引值等于 i i i時程序所執(zhí)行的指令。當(dāng)switch情況比較多時(>4),并且值的范圍跨度比較小時,就會使用跳轉(zhuǎn)表。跳轉(zhuǎn)表的優(yōu)點(diǎn)是執(zhí)行語句的時間與情況數(shù)量無關(guān)。
跳轉(zhuǎn)表對重復(fù)情況的處理就是簡單地使用相同的代碼標(biāo)號,而對于缺失的情況的處理就是使用默認(rèn)情況的標(biāo)號(loc_def)
6. 函數(shù)(過程)
6.1 過程機(jī)制
**傳遞控制:**調(diào)用時轉(zhuǎn)到調(diào)用過程代碼的起始位置,結(jié)束時回到返回點(diǎn)。
**傳遞數(shù)據(jù):**過程參數(shù)與返回值的傳遞。
**內(nèi)存管理:**過程運(yùn)行期間申請內(nèi)存,返回時解除分配。
該機(jī)制全部由機(jī)器指令實(shí)現(xiàn)。
6.2 棧
棧的結(jié)構(gòu):
注意:①%rsp始終指向棧頂元素的位置。②向低地址生長。
棧的操作
入棧指令
pushq src
從src取操作數(shù) → 將%rsp減8 → 將操作數(shù)寫到%rsp指向的位置
出棧指令
popq dst
從%rsp中保存的地址處讀取數(shù)值 → 將%rsp加8 → 將數(shù)值保存到dst(dst必須為寄存器或內(nèi)存操作數(shù))
6.3 過程控制流
過程調(diào)用
call func_label
執(zhí)行操作:
①將返回地址入棧(返回地址即為緊隨call指令的下一條指令的地址)
②跳轉(zhuǎn)到func_label(函數(shù)名字就是函數(shù)代碼段的起始地址)
過程返回
ret
執(zhí)行操作:
從棧中彈出返回地址,放入%rip里(pc)
參數(shù)傳遞
返回值:%rax
局部變量:僅在需要時申請棧空間
6.4 棧幀
棧的分配單位為幀,保存單個過程實(shí)例的狀態(tài)數(shù)據(jù)(參數(shù)、局部變量、返回地址等)
管理:進(jìn)入過程時申請空間(生成代碼,構(gòu)建棧幀,包括call指令產(chǎn)生的push操作),返回時解除申請(結(jié)束代碼,清理?xiàng)?,包括ret指令產(chǎn)生的pop操作)
寄存器保存約定
寄存器組是唯一被所有過程共享的資源,必須確保當(dāng)一個過程調(diào)用另一個過程時,被調(diào)用者不會覆蓋調(diào)用者稍后會使用的寄存器值。
①調(diào)用者保存Caller Saved
調(diào)用者在調(diào)用前,在它的棧幀中保存臨時值(寄存器)。
②被調(diào)用者保存Callee Saved
被調(diào)用者要先在自己的棧幀中保存,然后再使用寄存器。返回到調(diào)用者之前,恢復(fù)這些保存的值。
一個過程運(yùn)行的示例
long caller()
{
long arg1 = 534;
long arg2 = 1057;
long sum = swap_add(&arg1, &arg2);
long diff = arg1 - arg2;
return sum * diff;
}
對應(yīng)匯編代碼:
7. 數(shù)組
C語言可以產(chǎn)生指向數(shù)組中元素的指針,并對這些指針進(jìn)行運(yùn)算。在機(jī)器代碼中,這些指針會被翻譯成地址計(jì)算。
7.1 數(shù)組規(guī)則
T A[N];
來聲明數(shù)組(數(shù)據(jù)類型T,整型常數(shù)N)。會在內(nèi)存中分配一個L·N字節(jié)的連續(xù)空間(L為數(shù)據(jù)類型T的字節(jié)大小),用A來作為指向數(shù)組開頭的指針的標(biāo)識符。數(shù)組元素i會被存放在地址
x
A
+
L
?
i
x_A+L·i
xA?+L?i的地方。
7.2 指針運(yùn)算
7.3 二維數(shù)組
8. 結(jié)構(gòu)體和聯(lián)合
8.1 結(jié)構(gòu)體
結(jié)構(gòu)體的所有字段都存放在內(nèi)存中一段連續(xù)的區(qū)域內(nèi),而指向結(jié)構(gòu)體的指針就是結(jié)構(gòu)體第一個字節(jié)的地址。使用字段相對于起始地址的偏移量來維護(hù)各個字段的信息。
字段的順序必須與聲明一致,即便其他順序能使得內(nèi)存更加緊湊也不行。
由編譯器來決定總的尺寸和和字段的位置。
對齊
對齊后的數(shù)據(jù):基本數(shù)據(jù)類型需要K字節(jié),地址必須是K的倍數(shù)。
對其數(shù)據(jù)的動機(jī):內(nèi)存按4字節(jié)或8字節(jié)(對齊的)塊來訪問(4\8取決于系統(tǒng)),當(dāng)一個數(shù)據(jù)跨越2個頁面時,虛擬內(nèi)存比較棘手,不能高效地裝載或存儲跨越四字邊界的數(shù)據(jù)。
編譯器在結(jié)構(gòu)體中插入空白,以確保字段的正確對齊。
結(jié)構(gòu)體內(nèi)部:滿足每個元素的對齊要求。
結(jié)構(gòu)體整體的對齊存放:
? K = 所有元素的最大對齊要求值
? 則起始地址和結(jié)構(gòu)體長度必須是K的倍數(shù)。
空間的節(jié)?。捍蟪叽鐢?shù)據(jù)類型在前。
8.2 聯(lián)合
允許以多種類型來引用一個對象,用不同的字段來引用相同的內(nèi)存塊。一個聯(lián)合的總的大小等于它最大字段的大小。若一個數(shù)據(jù)結(jié)構(gòu)中的兩個不同字段的使用是互斥的,那么將這兩個字段聲明為聯(lián)合的一部分會減小分配空間的總量。
訪問位模式
聯(lián)合可以用來訪問不同數(shù)據(jù)類型的位模式。在聯(lián)合中,以一種數(shù)據(jù)類型來存儲聯(lián)合中的參數(shù),又以另一種數(shù)據(jù)類型來訪問,結(jié)果是他們會具有一樣的位表示,包括符號位字段、指數(shù)和尾數(shù)。
此時字節(jié)順序問題變得很重要,在小端與大端機(jī)器中對相同的位模式解讀不同。
9. 浮點(diǎn)數(shù)
寄存器
YMM是256位,32字節(jié)
XMM是128位,16字節(jié)
支持操作
①標(biāo)量操作:單精度/雙精度
②SIMD操作:單指令多數(shù)據(jù)操作,允許多個操作以并行模式執(zhí)行,對多個不同的數(shù)據(jù)并行執(zhí)行同一個操作。
內(nèi)存引用
參數(shù)傳遞:浮點(diǎn)型參數(shù)用YMM\XMM寄存器
使用不同的mov指令在YMM\XMM寄存器之間、或內(nèi)存和YMM\XMM寄存器之間傳送數(shù)值。
10.高級主題
10.1 理解指針
-
每個指針都對應(yīng)一個類型
通常如果對象類型位T,則指針的類型為T*
特殊的void *類型代表通用指針,可以通過顯式強(qiáng)轉(zhuǎn)或者賦值等隱式強(qiáng)轉(zhuǎn)來將其轉(zhuǎn)換成一個有類型的指針。
-
每個指針都有一個值
? 這個值是某個指定類型的對象的地址,特殊的NULL(0)值表示該指針沒有指向任何地方。
-
指針用’&'運(yùn)算符創(chuàng)建
對應(yīng)于機(jī)器代碼的leaq指令
-
數(shù)組與指針緊密聯(lián)系
一個數(shù)組的名字可以像一個指針變量一樣引用,但是不能修改。數(shù)組引用(a[3])與指針運(yùn)算和間接引用(*(a+3))有一樣的效果。
-
指針強(qiáng)轉(zhuǎn)
? 將指針從一種類型強(qiáng)制轉(zhuǎn)換成另一種類型,只改變它的類型,而不改變它的值。效果是改變指針運(yùn)算的伸縮。
- 指針可以指向函數(shù)
? 函數(shù)名為指針??梢詫⒅羔樫x值為函數(shù),并且用指針來調(diào)用函數(shù)。
? 函數(shù)指針的值是該函數(shù)機(jī)器代碼表示中第一條指令的地址。
10.1 內(nèi)存布局
堆中:大變量在高地址,小變量在低地址,便于內(nèi)存的回收與釋放,減少內(nèi)存碎片
10.2 緩沖區(qū)溢出 buffer overflow
C對于數(shù)組引用不進(jìn)行任何邊界檢查,而且局部變量和狀態(tài)信息(保存的寄存器值和返回地址等)都存放在棧中。對越界的數(shù)組元素的寫操作會破壞存儲在棧中的狀態(tài)信息,當(dāng)程序使用被破壞的狀態(tài),試圖重新加載寄存器或執(zhí)行ret指令時就會出現(xiàn)很嚴(yán)重的錯誤。
安全隱患
一種常見的狀態(tài)破壞稱為緩沖區(qū)溢出,通常在棧中分配某個字符數(shù)組來保存一個字符串,但是字符串的長度超出了為數(shù)組分配的空間。
緩沖區(qū)溢出的一個更加致命的使用就是讓程序執(zhí)行它本來不愿意執(zhí)行的函數(shù)。這是一種最常見的通過計(jì)算機(jī)網(wǎng)絡(luò)攻擊系統(tǒng)安全的方法。通常,輸入給程序一個字符串,這個字符串包含一些可執(zhí)行代碼的字節(jié)編碼,稱為攻擊代碼(exploit code),另外,還有一些字節(jié)會用一個指向攻擊代碼的指針覆蓋返回地址。那么,執(zhí)行ret指令的效果就是跳轉(zhuǎn)到攻擊代碼。
在一種攻擊形式中,攻擊代碼會使用系統(tǒng)調(diào)用啟動一個shell程序,給攻擊者提供一組操作系統(tǒng)函數(shù)。在另一種攻擊形式中,攻擊代碼會執(zhí)行一些未授權(quán)的任務(wù),修復(fù)對棧的破壞,然后第二次執(zhí)行ret指令,(表面上)正常返回到調(diào)用者。
防護(hù)
- 避免溢出漏洞
? 使用fgets代替gets: char *fgets(char *str, int n, FILE *stream)
? 一般用fgets(buf, sizeof(buf), stdin)
? 使用strncpy代替strcpy
? 在scanf函數(shù)中別用%s:使用fgets讀入字符串,或用%ns代替%s,其中n是一個合適的整數(shù)
- 使用系統(tǒng)級的防護(hù)
? ①隨機(jī)棧偏移(地址空間布局隨機(jī)化技術(shù)的一部分):程序啟動后,在棧中分配隨機(jī)數(shù)量的空間,將移動整個程序使用的棧空間地址,每次程序執(zhí)行,棧都重新定位,很難預(yù)測插入代碼的起始地址。
? ②非可執(zhí)行段:標(biāo)記存儲區(qū)為“只讀”或“可寫”,但不給予“執(zhí)行”權(quán)限,將stack標(biāo)記為不可執(zhí)行。文章來源:http://www.zghlxwxcb.cn/news/detail-471637.html
- 編譯器使用“棧金絲雀”(stack canaries) / 哨兵值(guard value)
? 在棧中buffer之后的位置放置特殊的值——金絲雀(canary),退出函數(shù)之前,檢查是否被破壞。編譯器默認(rèn)開啟。文章來源地址http://www.zghlxwxcb.cn/news/detail-471637.html
到了這里,關(guān)于《深入理解計(jì)算機(jī)系統(tǒng)(CSAPP)》第3章 程序的機(jī)器級表示 - 學(xué)習(xí)筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!