トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

IA32(x86)汎用命令対応のアセンブラ実装方法(1)

このエントリーをはてなブックマークに追加

[アセンブラ]

自作OS Advent Calendar 2016 11日目のために作成した記事です。

この記事はいろいろな用語が出てくるので、全て参考リンクを張っています。

OS自作入門でのアセンブラの使われ方

まず、なぜアセンブラが使われているのか?

次にアプリケーションレベルの話

  • libcを使わずシステムコールレベルの命令を実行
    • 作りたてのOSにはシステムコールを呼び出せる関数やライブラリが存 在しません
    • これはつまり標準出力に何か出したりメモリを確保したり、割り込み制御かけたりできないということで
    • ということは、そういった低レイヤをまかなうためのライブラリをビルドさせるか、自作するか2択になるわけです
    • OS自作入門では、bootpack.cにそういった命令のシンボル名を書き、その実装をnaskfunc.nasに書いてます
    • 最終的に作ったオブジェクトファイルは作った関数のシンボル名と実装を含むことになり、処理の中で関数が呼ばれると、naskfunc.nasに書かれたアセンブラ処理を実行 する という流れになるわけです

アセンブラを実装していく方法

次に、アセンブラを実装していく方法です今回のターゲットは単にnaskの構文を理解して、構文に対応する機械語を吐ければそれで十分です

  • サンプル
    • 最初のMOVを[ニーモニック]()^1
    • 単に命令(Instruction)と呼んでいいかもしれない

だいたい全部大文字

MOVAL,0x13; VGAグラフィックス、320x200x8bitカラー
MOVAH,0x00
INT0x10
  • naskはインテル記法なので
    • 命令の次にまずDEST(送り元)が来る
    • その次にSRC(送り先)が来る
    • 送り元とか送り先の意味合いは、命令の種類によって変化します

これをもうちょい一般化すると

  • MOV DEST, SRC ← 動作: DEST ← SRC

と書けそうです

  準備する資料

大元の種本とすべきなのは インテルR アーキテクチャー・ソフトウェア・デベロッパーズ・マニュアル なんでしょうが、わたしはめんどくさいのでWEBサイトに載っている それ の書き下しを参考にしています。

これを参考にすれば、どういう命令を出したい時にどういう機械語を出せばよいか仕様がわかります

  16bit, 32bitモードで出力される機械語の仕様

オペコードから導出される機械語の見取り図

以下は、i386のCPU

(a) 16-bit instruction mode (リアルモード)
 _________  ___________  ____________  _________
| Opcode  ||MOD-REG-R/M||Displacement||Immediate|
|         ||           ||            ||0-4 bytes|
|1-2 bytes|| 0-1 bytes ||            ||         |
|         ||           ||            ||         |
|         ||           ||            ||         |
 ---------  -----------  ------------  ---------

(b) 32-bit instruction mode (プロテクトモード)
 ........  ........  _________  ___________  .........  _________  _________
:Address ::Operand :| Opcode  ||MOD-REG-R/M|:Scaled   :|Displace-||Immediate|
:size    ::size    :|         ||           |:Index    :|ment     ||0-4bytes |
:0-1bytes::0-1bytes:|1-2 bytes|| 0-1 bytes |:0-1 bytes:|         ||         |
:Prefix  ::        :|         ||           |:         :|         ||         |
:67H     ::66H     :|         ||           |:         :|         ||         |
 ''''''''  ''''''''  ---------  -----------  '''''''''  ---------  ---------

図の中の用語の説明をしておきます機能レベルの話をしだすと記事がまとまらないので、まず概要のみ書きます。残りは別の記事で。。。

16-bit/32-bit共通

(a) 16-bit instruction mode (リアルモード)
 _________  ___________  ____________  _________
| Opcode  ||MOD-REG-R/M||Displacement||Immediate|
|         ||           ||            ||0-4 bytes|
|1-2 bytes|| 0-1 bytes ||            ||         |
|         ||           ||            ||         |
|         ||           ||            ||         |
 ---------  -----------  ------------  ---------
  • Opcode (オペコード
    • 例えば INT 0x13という命令であれば0xCD ibというオペコードがそれに対応する
    • アセンブラの出力は 0xcd, 0x13 になる
  • MOD-REG-R/M (ModR/M
    • 命令自体のオペコードと命令の対象となるレジスタによって変化する1byteのデータ
    • x86のCPUの命令が汚い原因の一つかも
  • Displacement (Disp)
  • Immediate (即値
    • 即値はそのままの数字のことです、大抵 0x が先頭につく

32-bit

(b) 32-bit instruction mode (プロテクトモード)
 ........  ........  _________  ___________  .........  _________  _________
:Address ::Operand :| Opcode  ||MOD-REG-R/M|:Scaled   :|Displace-||Immediate|
:size    ::size    :|         ||           |:Index    :|ment     ||0-4bytes |
:0-1bytes::0-1bytes:|1-2 bytes|| 0-1 bytes |:0-1 bytes:|         ||         |
:Prefix  ::        :|         ||           |:         :|         ||         |
:67H     ::66H     :|         ||           |:         :|         ||         |
 ''''''''  ''''''''  ---------  -----------  '''''''''  ---------  ---------

32bitモードの最初の2バイトはOverride prefixesと呼ばれる。なぜならそれらは常に存在するとは限らないからだ。 最初の1バイト目は命令に使われるオペランドのアド レス のサイズを変更する。 次の2バイト目はレジスタのサイズを変更する。

  • Address size Prefix byte
    • もし、CPUが16bit命令モードとして(プロテクトモードのみ)で動き、32bitレジスタが使われていればこれは無視される。もし、16bit命令が32bit命令モードで現れるのであれば、 16bitレジスタを選択するためこれが必要
    • 逆に、リアルモードで32bitのアドレッシング・モードを使うときもこれが必要
  • Operand size Prefix byte
    • 16bit命令モードで動作中(リアルモードもしくはプロテクトモード)、32bitレジスタが使われていれば、Override prefixes(0x66)が命令の前に付加される
  • Scaled Index byte (SIB)
    • x86の機械語コード中にあり、実効アドレスを指定したメモリーアクセスをする際の情報を与えるためのバイト。i386の32ビット以降で追加された。ModR/Mではカバーできん部分を指し示す。

これでようやく実装のための準備終了です、次回はより具体的な話を書きたいところです。

[^1]: 不正なリンクです。

お名前: コメント: