Mikan OSを自作してみる #7
今日やった内容
※アセンブリはコードのこと、アセンブラはそのコードを翻訳するプログラムやソフトウェアのこと
学習記録
<レジスタとは>
レジスタはCPUに内蔵された記憶領域である。CPUの外部にあるメインメモリとは役割が似ているが、メインメモリに比べてレジスタは容量が小さく読み書きが速いという特徴がある。
レジスタには汎用レジスタと特殊レジスタがある。
汎用レジスタ: CPUの演算対象に指定できる。 x86-64の汎用レジスタは、RAX, PBX, RCX, RDX, RBP, RSI, RDI, RSP, R8~R15の16個がある。
(使用例1)
アセンブリで加算命令addの場合
add rax, rbx ; オペコード(add) オペランド1(引数), オペランド2 (;はコメント)
これは rax += rbx; と一緒である。
特殊レジスタ値の記憶に加えて色々な役割があり、代表例は以下。
・RIP:CPUが次に実行する命令のメモリアドレスを保持するレジスタ
・RFLAGS:命令の実行結果によって変化するフラグを集めたレジスタ
・CR0:CPUの重要な設定を集めたレジスタ
(例2)
loop: dec rax ; decは減算命令でレジスタの値を1減らし、RAXがちょうど0になるとZFが1になる。rax-= 1 jnz loop ; jnzはJump if Not ZeroでZFが0の場合ジャンプする。 今回はRAXから1を引いた結果が0でない間、ループする。
<アセンブリの理解>
(1)
Z3foov: ; c++の関数foo push rbp ; push命令は、RSPレジスタの値を8だけ減らして RSPレジスタが指すメモリ領域にrbpレジスタの値をスタックの末尾に書き込む。 mov rbp, rsp ; mov命令は左を右にコピーする。rbp = rsp ; mov dword ptr [rbp -4] , 42 ; int i = 42 ; ; dwordは4バイトであることを意味する ;[xxx]をアドレスxxxへのメモリアクセスと認識する ;メモリアドレスがRBP-4へのメモリアクセスとなり、ここに42が書き込まれる
(2)
; intは4バイト(dword)でポインタは8バイト(qword) ; int* p = &i と同じで以下の(1),(2)の処理はポインタ*p に iのアドレスをコピーする ;lea命令は変数の実行アドレスを取得する ; rax = rbp - 4で変数iのアドレス取得、つまり&iと同じ lea rax, [rbp - 4] ;(1) rax にrbp-4のアドレスを格納 ; rbp-16を先頭とする8バイトのメモリ領域が変数pに対応する ;qwordは8バイトでptrはデータの型を指定する演算子でqword ptrで[rbp -16]が8バイトであることを表す mov qword ptr [rbp - 16], rax ;(2)アドレス値raxをrbp-16から8バイトのメモリ領域に書き込む ; int r1 = *p; mov rax, qword ptr [rbp - 16] ; raxにrbp-16から8バイトの値を覚えさせる (変数iのメモリアドレス) mov ecx, dword ptr [rax] ; ecxにraxが指すメモリ領域から4バイトを読む mov dword ptr [rbp-20], ecx ; ecxをrbp-20から4バイトのメモリ領域に書き込む ; *p + 1; mov rax, qword ptr [rbp - 16] ; raxにrbp-16から8バイトを覚えさせる mov dword ptr [rax], 1 ; 1をraxから4バイトのメモリ領域に入れる ; int r2 = i; mov ecx, dword ptr [rbp - 4] ; ecxにrbp-4から4バイトを覚えさせる mov dword ptr [rbp - 24], ecx ; ecxをrbp-24から4バイトのメモリ領域に入れる ; uintptr_t addr = reinterret_cast<uintptr_t>(p); mov rax, qword ptr [rbp - 16] ; raxにrbp-16から8バイトを覚えさせる mov qword ptr [rbp - 32], rax ; raxをrbp-32から8バイトのメモリ領域に入れる ; int* q = reinterpret_cast<int*>(addr); mov rax, qword ptr [rbp - 32] ; raxにrbp-32から8バイトを覚えさせる mov qword ptr [rbp - 40], rax ; raxをrbp-40から8バイトのメモリ領域に入れる pop rbp ret