2016
http://mooc.study.163.com/course/USTC-1000029000#/info
2015
http://mooc.study.163.com/course/USTC-1000072000#/info
實(shí)驗(yàn)樓,有實(shí)驗(yàn)環(huán)境
https://www.shiyanlou.com/courses/195
參考資料 深入理解Linux內(nèi)核第三版
1.存儲(chǔ)程序計(jì)算機(jī)工作模型
這個(gè)小節(jié),理解兩個(gè)問題
0x01什么是馮諾依曼體系結(jié)構(gòu)?
馮諾依曼體系結(jié)構(gòu)就是存儲(chǔ)程序計(jì)算機(jī),從如下兩個(gè)方面來看:
硬件方面,計(jì)算機(jī)可以抽象成由CPU,內(nèi)存組成,CPU和內(nèi)存之間通過總線連接,
CPU內(nèi)部有寄存器,如IP(Instruction Pointer)
16位的CPU叫IP
32位的CPU叫EIP
64位的CPU叫RIP
通常叫做IP,IP始終指向要執(zhí)行的代碼CS(Code Segment)
從程序員角度來看,
Memory holds instructions and data
CPU interpreter of instructions
0x02CPU識(shí)別什么樣的指令
API:程序員與計(jì)算機(jī)的接口界面
ABI:程序與CPU的接口界面
2.32位X86匯編基礎(chǔ)
這個(gè)小節(jié),理解幾種寄存器,幾種尋址方式
0x01 通用寄存器
寄存器 | 描述 |
---|---|
AX,EAX | 累加器(Accumulator) |
BX,EBX | 基地址寄存器(Base Register) |
CX,ECX | 計(jì)數(shù)寄存器(Count Register) |
DX,EDX | 數(shù)據(jù)寄存器(Data Register) |
EBP | 堆椀骶ǎ基指針(Base Pointer) |
ESI | 變址寄存器(Index Register) |
EDI | 變址寄存器(Index Register) |
ESP | 堆棧頂指針(Stack Pointer) |
0x02 段寄存器
寄存器 | 描述 |
---|---|
CS | 代碼段寄存器(Code Segment Register) |
DS | 數(shù)據(jù)段寄存器(Data Segment Register) |
ES | 附加段寄存器(Extra Segment Register) |
SS | 堆棧段寄存器(Stack Segment Register) |
FS | 附加段寄存器(Extra Segment Register) |
GS | 附加段寄存器(Extra Segment Register) |
0x03 幾種尋址方式
movl %eax, %edx // edx = eax; 寄存器尋址(register mode)
movl $0x123, %edx // edx = 0x123; 立即數(shù)(immediate)
movl 0x123, %edx // edx = *(int32_t*)0x123; 直接尋址(direct)
movl (%ebx), %edx // edx = *(int32_t*)ebx; 間接尋址(indirect)
movl 4(%ebx), %edx // edx = *(int32_t*)(ebx+4); 基址尋址(displaced)
3.反匯編一個(gè)簡單的C程序
這是一個(gè)實(shí)驗(yàn),實(shí)驗(yàn)樓有提供環(huán)境
https://www.shiyanlou.com/courses/195/labs/555/document
反匯編一段代碼,然后分析其匯編代碼
0x01 編譯下面這段代碼
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 1;
}
將這段代碼保存成main.c,用如下命令來進(jìn)行編譯
gcc –S –o main.s main.c -m32
命令執(zhí)行完后,生成main.s這個(gè)匯編文件
0x02 分析匯編代碼
# 分析前先了解如下幾個(gè)指令
pushl %eax
subl $4, %esp
movl %eax, (%esp)
popl %eax
movl (%esp), %eax
addl $4, %esp
call 0x12345
pushl %eip(*)
movl $0x12345, %eip(*)
ret
popl %eip(*)
enter
pushl %ebp
movl %esp, %ebp
leave
movl %ebp, %esp
popl %ebp
# 用(*)標(biāo)注的寄存器,說明該寄存器不能被程序員直接修改,必須通過特定的指令才能使其改變
下圖是main.s
main.s
下面是對這段代碼的堆棧的分析
堆棧分析