はじめに
nasmで1~100を表示させるコードを書いたので、ここにメモしました。
基本的には前回の応用です。読んでください。
コード
ソースコード
; 初期設定
extern printf ; printf関数を持ってくる
; データセクション
section .data
fmt: db "%d", 10, 0 ; printfで用いるフォーマット
; コードセクション
section .text
global _start ; _startを指名
; スタート
_start:
; 1. 必要な値の代入
mov rdx, 1 ; カウントの初期化
mov rcx, 100 ; ループ回数
; 2. ループの先頭
_loop:
; 3. 維持して置きたい値の避難
push rcx ; rcxの避難
push rdx ; rdxの避難
; printfに用いる値のセット
mov rdi, fmt ; フォーマット
mov rsi, rdx ; カウントしている値
; コール
call printf ; printfをコール
; 4. スタックの値をレジスタに戻す
pop rdx ; rdxを持ってくる
pop rcx ; rcxを持ってくる
; 5. インクリメントする
add rdx, 1 ; rdxに1加算
; 6. ループバック
loop _loop ; ループバック
; 後処理
fin:
mov rax, 1 ; システムコール番号(sys_exit)
mov rbx, 0 ; 終了ステータスコード
int 0x80 ; システムコール
実行
$ nasm -f elf64 ファイル名
$ gcc 生成したオブジェクトファイル名 -nostartfiles -no-pie
$ ./a.out
1
2
3
4
.
.
.
97
98
99
100
解説
1. 各値の指定
表示するようの値としてrdx
を用いるので、初期値として1を代入します
x86-64だとrcx
に置いた回数だけループされるので、以下のコードでrcx
に100を入れます。
mov rdx, 1
mov rcx, 100
2. 6. ループをセット
_loop
というラベルを貼り、loop _loop
が来たときrcxがゼロ以外ならループします。
_loop:
ここにコード
loop _loop
3. 維持して置きたい値の避難
printfのコール時にレジスタの値が消えてしまうので、スタックに避難させます。
push rcx
push rdx
4. 避難させたスタックをレジスタに戻す
上記のスタックに避難させた各値をレジスタに戻します。
pop rcx
pop rdx
5. rdxに1加算
rdx
に1加算します。
add rdx, 1
さいごに
こんな感じで、1~100を呼び出しました。
何か間違ったこと等あればコメントください。