X86アセンブラ/基本的なFAQ
このページでは、アセンブリ言語でのプログラミング初心者の基本的なFAQについて答えよう。
目次 |
コンピュータはアセンブリ言語をどのように読んで理解するのか?[編集]
コンピュータは実際のところ読みも、理解も、何もそれ自体ではしないが、しかしこういう答えが求められている訳ではないだろう。事実は、コンピュータはあなたの書いたアセンブリ言語を読むことはできないということである。アセンブラがアセンブリ言語を機械語と呼ばれる2進数の情報の形に変換し、コンピュータはそれを使って動作するのである。コードがアセンブルされていないならば、それはコンピュータにとって全く意味不明である。
アセンブリ言語のそれぞれの命令は、通常ただ一つの機械語に対応しているので白紙と鉛筆とアセンブリ命令のリファレンスブックだけがあれば、「ごく普通の人」でもこの作業(ハンドアセンブル)を実行することができる。実際、コンピュータが使われだした最初の頃は、これは一般的にされていたことであって、基本的なコンピュータプログラムのいくつかにとっては「ハンドアセンブル」するというのは必要なことであった。このころの古典的な例としては、スティーブ・ウォズニアックによるものがある。彼にとっての最初のApple Iコンピュータで使うために、Integer BASICインタプリタの全てを6502機械語にハンドアセンブルした。しかし、覚えておいてほしいのだが、商業的に配布されたソフトウェアのためにこのような作業がされたのは、非常にめずらしいことであるから話題になるのである。本当にほんの少しのプログラマが、実際に少数の命令についてハンドアセンブルをした経験を持っているにすぎないし、経験があるとしても学校の宿題としてやったことがあるに過ぎない。
WindowsとDOSとLinuxでアセンブリ言語は同じなのか?[編集]
この質問への答えはイエスであり、ノーでもある。基本的なx86機械語はプロセッサにのみ依存する。x86バージョンのWindowsとLinuxは明らかにx86機械語で作られている。x86アセンブリ言語でのプログラミングはLinuxとWindowsとで少し異なっている。
- Linuxが動作している環境では、最も一般的なアセンブラはAT&T記法を採用するGASアセンブラか、MASMに似た記法を採用するNASMという名前でも知られるNetWideアセンブラである。
- Windowsが動作している環境では、最も一般的なアセンブラはMASMであり、インテル記法が採用されている。
- 使用可能なソフトウェア割り込みとその機能はWindowsとLinuxで異なっている。
- 使用可能なコードライブラリはWindowsとLinuxで異なっている。
同じアセンブラを使うならば、基本的なアセンブリコードはオペレーティングシステムによらず基本的には同じである。 しかし、Windowsと連携するならば、Linuxと連携する場合とコードは異なったものとなる。
どのアセンブラがベストか?[編集]
簡単に答えると、どのアセンブラも他のどのアセンブラよりも似たり寄ったりであり、個人の好みの問題である。
もう少し詳しく答えると、アセンブラはそれぞれの利点と欠点がある。あなたがGAS構文しか知らないとしたら、あなたは多分GASを使いたがるであろう。インテル文法を知っておりWindowsマシンで仕事をしているのであれば、MASMを使いたくなるかもしれない。MASMやGASの癖や複雑さが好きでないならば、FASMやNASMを使いたくなるかもしれない。この本では第2節でそれぞれのアセンブラの違いを扱う。
アセンブリ言語を知る必要があるか?[編集]
ほとんどのコンピュータに関連する作業をするためにアセンブリ言語を知る必要はないが、知っておくけば役に立つ。アセンブリ言語を学ぶことは、新しいプログラミング言語を学ぶということではない。新しいプログラミングプログラミングを始めようとするとき(プロジェクトがブートローダやデバイスドライバ、カーネルでなければ)、アセンブリ言語はやっかいものとして避けられるだろう。例外は、絶対的にパフォーマンスが重要であったり、コンパイラが最適でないコードを生成する場合である。しかし覚えておいてほしいのは、不完全な最適化は全ての悪の根源である。ただし、最適化技術が理解されており最初から計画されていれば、計算量が重要となるリアルタイムなタスクでは簡単に十分な最適化が実施できる。
しかし、アセンブリ言語を学ぶことによってコンピュータがその内部でどのように働いているのかについての詳細な見識を得ることができる。C言語やAdaといった高水準言語でプログラムを書いても、コードは全て最終的にはコンピュータの実行できる機械語の命令に変換される必要がある。プロセッサが何ができるかについて正確に理解することは、最も基本的なレベルにおいて、高水準言語でプログラミングをする際の助けとなる。
コードにはどのようにフォーマットを使うべきか?[編集]
ほとんどのはアセンブリコードの命令は、それぞれを各行に書き改行で分けている。また、ホワイトスペースが命令、オペランドなどを分けるのに使われる。正確に言えば、コードにどのようなフォーマットを採用すべきかは、あなたにまかされている。しかし、一般的な方法というものはいくつかある。
一つは全てを1行ずつ書く方法である。
Label1: mov ax, bx add ax, bx jmp Label3 Label2: mov ax, cx ...
もう一つは、ラベルを最初の列に書き、命令をそれ以降の列に書く方法である。
Label1: mov ax, bx add ax, bx jmp Label3 Label2: mov ax, cx ...
ほかにも、ラベルで1行を使い、命令を少しインデントして書く方法もある。
Label1: mov ax, bx add ax, bx jmp Label3 Label2: mov ax, cx ...
これらに加えて、ラベルを最初の列に書き、命令を以降の列に書くが、ラベルには別の行を使う方法もある。
Label1: mov ax, bx add ax, bx jmp Label3 Label2: mov ax, cx ...
本当にたくさんの書き方があるが、アセンブリプログラマが一般的に従っているルールがいくつかある。
- ラベルは、他のプログラマがどこにラベルがあるかはっきり分かるように書く。
- 構造(インデント)はコードが読みやすいようにする。
- コメントを使い、何をしているのか説明する。アセンブリ・コードの意味は、すぐにははっきりしないことが多いからである。