「Linuxカーネルの解析」
第一章コンピュータの仕事
1.1プログラム内蔵方式ワーキングモデル
- ノイマン型
コンピュータアーキテクチャのさまざまな「客観法律」を遵守する必要がありますStructureチャート
- コアノイマン型は、プログラム内蔵方式です。
命令やデータを保持するためのメモリ、CPUはバスによって相互に接続され、これらの命令を、解釈し、実行する責任があります。
プログラム内蔵方式の模式図
x86-32コンピュータのために、EIPは、メモリ命令にポイントを登録し、EIPは、一つ(命令を追加)だけインクリメントされます。
1.2 x86-32アセンブラの基礎
1.2.1 x86-32 CPUレジスタ
- Eレジスタは、典型的には、32ビットを開始します。
- 32ビットは、EAX、EBX、ECX、EDXとだけでなく、データを送信することができ、一時的なデータは、算術論理演算の結果を保存し、それはポインタレジスタとしても使用することができるレジスタ。
- セグメントレジスタ
スニペット:CSを使用して:EIPを正確に次の命令のメモリアドレス指定(コード内のコードセグメントを知るために、すなわち、最初の必要性を、次いでコードセグメントEIPにおける命令アドレスの相対オフセットを知る必要があります)。
- スタックセグメント:各プロセスは独自のスタックセグメントを持っています。
リボンRの先頭を指すは、64ビットレジスタです。
1.2.3一般的なアセンブリ命令とアドレッシングモード
- 最も一般的には、アセンブリ命令のmov命令は、MOVB手段8であり; MOVW手段16; MOVL手段32; MOVQ 64を意味します。
- アドレッシング
- x86-32ほとんどの命令は直接メモリにアクセスすることができますが、そのようなので、上のMOV、プッシュ/ポップととして直接メモリ操作にはいくつかの命令が、あります。
- プッシュ:PUSHLプッシュ32が示されています。
pushl %eax
EAXレジスタ・スタックの値がスタックに押されています。実際には二つの動作:
①ESPの値がスタックマイナス4をスタックに登録します。(スタックが下方に成長するので、SUBL減算命令を使用するので、それは、確保されたメモリセルスタックです)
subl $4, %esp
②間接アドレッシングは、次にESPアウト確保されたメモリセルへのポイントを登録ESPレジスタポイントに登録EAXの値を配置することです。
movl %eax, (%esp)
- スタック:
popl %eax
EAXは、スタックの位置からスタックに登録し、スタックから1つのメモリセルスタックを取ります。実際には二つの動作:
①スタックの最上部にEAXレジスタの値。
movl (%esp), %eax
スタック上方バックオフ一つのメモリセルの位置に対応する命令②ADDLプラス4とスタックの上部、すなわちスタック収縮。
addl $4, %esp
各実行スタックが成長しているスタックが収縮されPUSHL命令は、命令がPOPL実行します
- コール命令は、関数呼び出し、2つの動作の等価です。
push %eip
movl f %eip
- これは、関数の戻り命令RETです
- EIPとプログラマが直接、間接的に修飾された専用の命令(例えば、通話、RETのJMPなど)を変更することはできません。
1.2.4アセンブリコードの例構文解析
以下の2つの断片を変更の効果と同じです
次の断片が少し複雑です(ブックP12)
1.3シンプルなC言語プログラムをコンパイルし、そのアセンブリ命令の実行を分析
ビューに「LS」コマンド
vi main.c
VIMエディタmain.cのファイルを開くためのコマンド
gcc main.c
コマンドは直接コンパイルし
echo $?
、このプログラムの戻り値をチェックするためのコマンドを
gcc -S -o main.s main.c -m32
アセンブリコードにコマンドにコンパイルのmain.c
とVIMエディタで
g/\.s*/d
すべての追加情報を削除するためのコマンド、「クリーン」なアセンブリコードへのアクセス
- 上述した「クリーン」なアセンブリコードの分析
1 g:
2 pushl %ebp //将EBP压栈,将位置4存到位置7;ESP也指向位置7。
3 movl %esp, %ebp //将EBP也指向位置7。
4 movl 8(%ebp), %eax //EBP变址寻址,加8,即指向位置7不动,并把位置5的内容(即立即数8)放入EAX(取出函数g的参数)。
5 addl $3, %eax //将立即数3加到EAX中,即8+3,EAX为11。
6 popl %ebp //将位置7的内容(即位置4)放回EBP(即恢复函数f的函数调用堆栈基址EBP),即EBP指向位置4;【同时ESP加4,指向位置6】。
7 ret //(popl%eip)将ESP所指向的内容,即行号15放入EIP,即EIP指向行号15;同时ESP加4,即指向位置5。
8 f:
9 pushl %ebp //将EBP向下移动(从EIP的位置3开始),指向位置4。
10 movl %esp, %ebp //将ESP也指向EBP的位置4。
11 subl $4, %esp //ESP减4,指向位置5。
12 movl 8(%ebp), %eax //EBP变址寻址8,向上移动两个存储单元即加两个标号的位置,即指向位置2;并将位置2存储的立即数8放到EAX中。
13 movl %eax, (%esp) //将EAX放入ESP中,即立即数8放入位置5。
14 call g //类似第22行,将ESP指向位置6,;把EIP行号15放到位置6,并指向函数g的位置即第2行。
15 leave //撤销函数堆栈,等价于=(movl %ebp,%esp和popl %ebp),即将EBP的内容(位置4)放入ESP,即ESP也指向位置4;【然后把位置4的内容(即位置1)放回EBP,即EBP指向位置1;同时ESP加4,指向位置3。】
16 ret //将ESP所指向的位置3的内容(即行号23)放到EIP中,即EIP指向行号23,;同时ESP加4,指向位置2。
17 main:
18 pushl %ebp //开始执行第一条指令,EIP自动加1即指向行号19;把EBP的值压栈,先将EBP指向位置1,再将EBP的值标号0。
19 movl %esp, %ebp //EIP自动加1即指向行号20;将EBP指向位置1。
20 subl $4, %esp //EIP自动加1即指向指向行号21;将ESP减4,即向下移动,指向位置2。
21 movl $8, (%esp) //EIP自动加1即指向行号22;把立即数8放入ESP,仍指向位置2(20和21行同作为压栈f函数所需参数)。
22 call f //执行此行时,EIP已经自动加1指向了下一行即指向行号23(pushl %eip),然后将函数f的开始指令放入EIP(movl f %eip),即EIP指向函数f的位置即第9行。
23 addl $1, %eax //将EAX加立即数1,即11+1,EAX的值为12,(EAX是默认存储函数返回值的寄存器)。
24 leave //撤销函数main堆栈,将EBP和ESP都指回位置1,【同时把位置1存储的内容(即位置0)放到EBP,即EBP指向位置0;并ESP加4,也指向位置0】。
25 ret //指令结束。
[]はかなり全体の内容を理解していませんでした
- 休暇命令順序は同等です:
movl %ebp,%esp
popl %ebp
- 命令を入力することに相当します。
pushl %ebp
movl %esp, %ebp