OS自作入門 on Ubuntu 16.04 (2日目)
2日目の内容は,1日目で作成したアセンブラコード(helloos2.s)のプログラム本体をちゃんとアセンブラで実装するようです.プログラム本体は DB 命令でよくわからない16進数のデータを打ち込んでいますが,これは言わば機械語のプログラムです.この機械語のプログラムをちゃんとアセンブラコードとして書いていきましょう.
という行を追加する必要があります.
NASK の ORG 命令はプログラムの本体がどこにあるかを指定しますが,GAS ではプログラム中に書くのではなく,アセンブラにオプションとして与える方針です.とりあえずスキップして先に進みましょう.後でこれに対応する方法を書きます.
と書けばOKです.ところで, helloos2.s では JMP 命令の部分は
となっていました.これが jmp 命令を機械語に翻訳した機械語だったんですね.jmp 命令より下からプログラム本体までは変更がないので,プログラム本体までスキップします.
さらに,代入元(ソース)と代入先(デスティネーション)の位置が反対になっています.
は AX レジスタに 0 を代入するという意味ですから,
というイメージです.一方,GAS では
と書きます(AXレジスタは16ビットなので movw を使います).つまり,
というイメージです.ソースとデスティネーションが反対になっていることが分かると思います.
movb の場合も見てみましょう.
というのがありますが,AHレジスタは8ビットですので,
となります.NASK(NASM)ではどちらも同じ MOV 命令を使っていましたが,GAS では区別していることに注意しましょう.
もうひとつ,MOV 命令の中には
という書き方があります.これはメモリアクセスですが,GAS では [] の代わりに () を使いますので,
となります(AL レジスタが8ビットなので movb を使います).
は
となります.
CMP AL, 0
は,AL レジスタを使っているところからも分かるように,以下のように cmpb を使います.
とすればOKです.
この Makefile を使って,
とすれば実行まで一気にやってくれます.
今日はここまで.
ツールのインストール
1日目に使ったツール以外にインストールするものはありません.helloos5.s への書き換え
16ビットバイナリの生成
2日目のアセンブラの説明を読むと分かるのですが,ここで出てくるアセンブラコードは 16 ビットの命令を前提としています.AX レジスタが 16 ビットというところから分かると思います.ただ,Ubuntu 16.04 で x86_64 版は 64 ビット OS ですので,16 ビット命令として機械語を生成する必要があります.ですので,アセンブラコードの先頭に.code16
という行を追加する必要があります.
レジスタの書き方
NASK(NASM)では AX レジスタは単に AX と記述すればよかったのですが,GAS では % をつける必要があります.AX レジスタであれば,%axという具合です.数値の書き方
NASK(NASM)では単に 0 と書けばよかったのですが,GAS では $ をつけて $0 とします.16進数の場合も同じで,0x0e を GAS では $0x0e と書きます.ORG 命令
コードの最初に出てくる ORG 命令ですが,これに対応する GAS の命令ないようです.無いってどういうこと?と疑問が膨らみますが,どうやら NASK(NASM)と GAS は構文が異なるだけでなく,細かい違いもあるようです.NASK の ORG 命令はプログラムの本体がどこにあるかを指定しますが,GAS ではプログラム中に書くのではなく,アセンブラにオプションとして与える方針です.とりあえずスキップして先に進みましょう.後でこれに対応する方法を書きます.
JMP 命令
ORG 命令の下には JMP 命令があります.これは GAS でも同じようにjmp entry
と書けばOKです.ところで, helloos2.s では JMP 命令の部分は
.byte 0xeb, 0x4e
となっていました.これが jmp 命令を機械語に翻訳した機械語だったんですね.jmp 命令より下からプログラム本体までは変更がないので,プログラム本体までスキップします.
MOV 命令
プログラム本体の最初に出てくる MOV 命令は,GASだと微妙に違っています.GAS では場合によって movw と movb の2種類を使い分けます.movw の w はワードを意味していて,オペランドが2バイト(16ビット)の場合です.一方,movb の b はバイトを意味していて,オペランドが1バイト(8ビット)の場合です.GAS 用に変換するときは注意深く使い分けましょう.さらに,代入元(ソース)と代入先(デスティネーション)の位置が反対になっています.
MOV AX, 0
は AX レジスタに 0 を代入するという意味ですから,
AX ← 0
というイメージです.一方,GAS では
movw $0, %ax
と書きます(AXレジスタは16ビットなので movw を使います).つまり,
0 → AX
というイメージです.ソースとデスティネーションが反対になっていることが分かると思います.
movb の場合も見てみましょう.
MOV AH, 0x0e
というのがありますが,AHレジスタは8ビットですので,
movb $0x0e, %ah
となります.NASK(NASM)ではどちらも同じ MOV 命令を使っていましたが,GAS では区別していることに注意しましょう.
もうひとつ,MOV 命令の中には
MOV AL, [SI]
という書き方があります.これはメモリアクセスですが,GAS では [] の代わりに () を使いますので,
movb (%si), %al
となります(AL レジスタが8ビットなので movb を使います).
ADD 命令
ADD 命令も MOV 命令と同じで addw と addb があります.また,ソースとデスティネーションが入れ替わるのも同じです.したがって,ADD SI, 1
は
addw $1, %si
となります.
CMP 命令
CMP 命令にも cmpw と cmpb があります.ソースとデスティネーションも入れ替わっています.CMP AL, 0
は,AL レジスタを使っているところからも分かるように,以下のように cmpb を使います.
cmpb $1, %al
JE 命令, JMP 命令, INT 命令, HLT 命令
これらの命令には違いがありません.アセンブラコード
以下は helloos5.s です..code16
jmp entry
.byte 0x90
.ascii "HELLOIPL"
.word 512
.byte 1
.word 1
.byte 2
.word 224
.word 2880
.byte 0xf0
.word 9
.word 18
.word 2
.long 0
.long 2880
.byte 0,0,0x29
.long 0xffffffff
.ascii "HELLO-OS "
.ascii "FAT12 "
.org .+18
# プログラム本体
entry:
movw $0, %ax
movw %ax, %ss
movw $0x7c00, %sp
movw %ax, %ds
movw %ax, %es
movw $msg, %si
putloop:
movb (%si), %al
addw $1, %si
cmpb $0, %al
je fin
movb $0x0e, %ah
movw $15, %bx
int $0x10
jmp putloop
fin:
hlt
jmp fin
# メッセージ部分
msg:
.byte 0x0a, 0x0a
.ascii "hello, world"
.byte 0x0a
.byte 0
.org 0x1fe
.byte 0x55, 0xaa
実行
Makefile は後回しにして,とりあえず実行してみます.リンカオプション
OS のイメージを作成するにあたり,上の ORG 命令でスキップした「プログラムの開始地点」をオプションで与えなければなりません.これを与えるのがリンカオプションです.以下の記述を binary.ls として与えます.OUTPUT_FORMAT(binary) OUTPUT_ARCH(i386) SECTIONS { . = 0x7c00; .text : {*(.text)} }
OS イメージの作成
以下の手順で OS イメージを作ります.$ as -32 helloos5.s -o helloos5.o $ ld helloos5.o -T binary.ls -o helloos5.bin $ mformat -f 1440 -C -B helloos5.bin -i helloos5.img ::
OS の起動
これは1日目と同じで$ qemu-system-x86_64 -fda helloos5.img
とすればOKです.
Makefile
できるだけ忠実に Makefile を書いてみました.ただし,install は不要ですので書いてありません.# コマンド helloos5.bin: helloos5.s Makefile as -32 helloos5.s -o helloos5.o ld helloos5.o -T binary.ls -o helloos5.bin helloos5.img: helloos5.bin Makefile mformat -f 1440 -C -B helloos5.bin -i helloos5.img :: img: make -r helloos5.img asm: make -r helloos5.bin run: make img qemu-system-x86_64 -fda helloos5.img
この Makefile を使って,
$ make run
とすれば実行まで一気にやってくれます.
今日はここまで.
コメント
コメントを投稿