過程が大事

学んだことを適当にアウトプットします

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