前回までの記事ではコピー元やコピー先について体系的な説明を行わず、「どこからどこへコピーする」という形で説明していた。
今回はその指定方法についてスタック以外のデータ格納領域も含めて説明する。
C言語プログラムとバイナリコード
グローバル変数及び静的変数を含むプログラム①をコンパイルし、アセンブラコードに変換すると②のようになる。
① C言語プログラム
int global_data;
main()
{
static int main_data = 0x1000;
int array_data[5];
int stack_data = 0x10;
int i = 4;
array_data[i] = 0;
global_data = main_data + stack_data;
}
このプログラムでは以下の変数が宣言されている。
- global_data:グローバル変数
- main_data:main()関数内の静的変数
- stack_data:スタック上に確保されるローカル変数
- array_data[5]:スタック上に確報される配列
② アセンブラコード
.bss
global_data resd 1 ; グローバル変数(未初期化)
.data
main_data dd 1000h ; static変数(初期化ありなのでデータ領域)
.text
global main
main:
push ebp
mov ebp, esp
sub esp, 28 ; array_data(20) + stack_data(4) + i(4)
; stack_data = 0x10
mov DWORD PTR [ebp-4], 10h
; i = 4
mov DWORD PTR [ebp-8], 4
; array_data[i] = 0
mov eax, DWORD PTR [ebp-8]
; eax = i
mov DWORD PTR [ebp-28 + eax*4], 0
; global_data = main_data + stack_data
mov eax, DWORD PTR main_data
add eax, DWORD PTR [ebp-4]
mov DWORD PTR global_data, eax
mov esp, ebp
pop ebp
ret
ディレクティブとデータ定義
「.」で始まる行はディレクティブと呼ばれ、コード配置やデータ定義など、機械語生成以外の制御を指示する疑似命令である。
.bss
global_data resd 1
- .bss は未初期化データ領域を表す
- global_data はラベル(アドレスを示す)
- resd 1 は32bit領域を1つ確保する命令。データ型により、resb、resw等がある。
※ .bss 領域は通常、プログラム起動時に0で初期化される。
.data
main_data dd 1000h
- .data は初期化済みデータ領域
- dd は32bitデータ定義命令。データ型により、db、dw等がある。
- 初期値は 1000h
.text
- .textは実行コード(命令列)が格納される領域
対象となる計算処理命令のアドレッシングモード
アドレッシングモードとは、CPUが命令を実行する際に処理対象となるデータの格納場所(メモリアドレスやレジスタ)を指定する方法のことである。
ここでは各命令のアドレッシングモードについて説明する。なお、説明対象を赤文字としている。
① 即値アドレッシング
命令内に直接値を指定する方法
mov DWORD PTR [ebp-8], 4
② レジスタアドレッシング
レジスタを直接指定する方法
mov eax, DWORD PTR [ebp-8]
③ 直接アドレッシング
メモリアドレス(ラベル)を指定する方法
下の例では静的変数であるmain_data というラベルの付いたメモリのアドレスを指定している
グローバル変数へも同様の方法で指定する
mov eax, DWORD PTR main_data
④ ベースレジスタ相対アドレッシング
ebp(ベースポインタ)を基準に nバイトずらしたアドレスの値を指定する方法
スタック上のローカル変数などに使用する
mov DWORD PTR [ebp-8], 4
⑤ インデックス付きアドレッシング
ebp(ベースポインタ)を基準に、インデックスレジスタの値を足したアドレスの値を指定する方法
下の例ではebp – 28 (ローカル変数 array_dataの先頭アドレス)にレジスタeax(インデックスレジスタの値)×4(要素のサイズ) を足したアドレスを指定している
eaxには1つ前の命令でローカル変数 i の値を入れているので、array_data[i] を指し示すことになる
mov DWORD PTR [ebp-28 + eax*4], 0
変数の種類とアドレッシングモード
ここまで命令毎にアドレッシングモードの説明を行った。
次にデータの格納場所毎にどのアドレッシングモードが使用されるかをまとめる。
| 種類 | 配置 | アドレッシング |
|---|---|---|
| グローバル変数 | .bss / .data | 直接 |
| 静的変数 | .bss / .data | 直接 |
| ローカル変数(スタック) | スタック | ベースレジスタ相対 |
| ローカル変数(最適化時) | レジスタ | レジスタ |
| 引数 | スタック | ベースレジスタ相対 |
| 配列 | スタック | インデックス付き |
以上、簡単ですが自動変数以外の変数の確保される領域とアクセスする方法についての説明でした。
