KDOC 141: Cのポインタ操作をアセンブリで見る
この文書のステータス
- 作成
- 2024-04-29 貴島
- レビュー
- 2024-05-06 貴島
概要
ポインタ型の引数に代入すると、関数をまたいで変更を反映できる(参照渡し)。C言語では返り値を複数返せないので、複数必要なときはこれを使う。
#include <stdio.h> void inc(int *a) { // アドレスを受け取る *a = *a+1; // アドレスが参照する値を反映する } int main(void){ int a = 0; inc(&a); // アドレスを渡す inc(&a); printf("%d",a); // 2 }
何が起きているのか、生成されたアセンブリを見て確かめる。
アセンブリで見ると
↓こうなっている。即値の代入とじつはあまり変わらない。スタックに入っている値を使うか、スタックのアドレスを使うかだけの違い。
// ↓新しいスタック割当。sp -> スタックの底 addi sp,sp,-32 // ↓元々のレジスタの値をスタックに退避する sw ra,28(sp) sw s0,24(sp) // ↓退避したのでs0を上書きして新しいスタックフレームに移動させる。s0: スタックの一番上、開始アドレス addi s0,sp,32 // ↓積んだスタックの一番上の**アドレスを**計算してa5に格納 addi a5,s0,-24 // ↓a5(アドレスが入ってる)をスタックに保存 sw a5,-20(s0) // ↓a5をスタックからロード(storeとloadで、結果としてa5の値は変わらない) lw a5,-20(s0) // ↓即値41をa4にロード li a4,41 // ↓41番地にa5を保存 sw a4,0(a5) nop ;; レジスタを元に戻す lw ra,28(sp) lw s0,24(sp) addi sp,sp,32 ;; 呼び出し先に戻る jr ra
関連
- KDOC 140: 『自作エミュレータで学ぶx86アーキテクチャ』。出てきた内容を確かめた