LoginSignup
29
25

More than 5 years have passed since last update.

64ビット CPU の遊び方

Posted at

はじめに

最近の PC やサーバ用 CPU は特別なものを除けば x64 とか AMD64 とか呼ばれる 64ビット CPU が主流です。しかし、スクリプト言語や Java などを使っている限り、そのことを実感できません。実際に実感するためには、やはりアセンブラが一番です。

ということでアセンブラを使って64ビット CPU で遊んでみました。試した環境としては、AWS で稼働している Ubuntu 14.04LTS です。具体的にはこんな感じです。

  • Single core Intel Xeon CPU E5-2670 v2
  • Host: ip-172-??-??-130 Kernel: 3.13.0-36-generic x86_64 (64 bit)

アセンブラとは

アセンブラとは正確にはアセンブリー言語とか言います。CPU は機械語だけしか解釈しませんが、命令がその機械語に1対1に対応するような言語です。言い直せば、機械語をシンボルを使って記述する言語みたいな感じです。

Linux の C コンパイラ (gcc) には as というアセンブラが付いてきますが、ここでは nasm というアセンブラを使っています。理由は、けっこうしっかりしたマニュアル (英語ですが) が付いているのと、記述方法が as よりシンプルなためです。

nasm のインストール

nasm のインストールですが、Ubuntu では apt-get で簡単にインストールできます。もし、gcc が入ってない場合は、gcc もインストールしておく必要があります。

$ sudo apt-get install nasm

予備知識

アセンブラは機械語と1対1に対応しています。したがって、アセンブラ (アセンブリー言語) を知っていても、CPU の構成とか機械語を知らないとプログラムは作れません。ここでそこまで書いていたら長くなってしまいますし、本題に入るまでに時間がかかってしまうので、それについては読者が知っているものとします。

それでは Hello World から

アセンブラは機械語と1対1ですから、他の言語だと1行ですむようなプログラムもこんなに長くなります。

hello.asm
section  .data                  ; データセクションの定義
message  db 'Hello, World', 0x0a
length   equ $ -message         ; 文字列の長さ
section  .text
global   _start                 ; エントリーポイント

_start:
mov     rcx, message            ; 文字列の先頭アドレス
mov     rdx, length             ; 文字列の長さ
mov     rax, 4                  ; 出力(sys_write)
mov     rbx, 1                  ; ファイルハンドル(1 = 標準出力)
int     0x80                    ; システムコール
mov     rax, 1                  ; sys_exit
mov     rbx, 0                  ; 終了ステータスコード
int     0x80                    ; システムコール

下がその実行例です。

ubuntu@ip-172-??-??-130:~/workspace/nasm$ bin/hello
Hello, World
ubuntu@ip-172-??-??-130:~/workspace/nasm$

ここでメッセージを表示する部分は最初の int 0x80 です。これは何かというと、ソフトウェア割り込み命令ですね。0x80 番の割り込みを行うと rax で指定した番号に対応する OS で用意されているエントリーポイントへ飛んでいくというものです。

最後にも int 0x80 がありますが、こちらはプログラムを終了する (OS に制御を返す) ためのシステムコールです。ところで rax とか rbx とかは 64bit 汎用レジスタと呼ばれるもので、CPU 内部の演算に使用するための一時記憶用高速メモリみたいなものです。mov は move 命令というもので即値データやレジスタのデータなどを他のレジスタにコピーします。

CPU の命令や構造ですが、こちらがわかりやすそうです。

Introduction to x64 Assembly

ビルド方法

このプログラムをアセンブル+リンクするには下のようにします。この例で、ソースファイル (.asm) は src/ に、中間ファイル (.o) は obj/ に、実行ファイルは bin/ に置くものとします。

nasm -f elf64 -o obj/$1.o src/$1.asm
ld -s -o bin/$1 obj/$1.o

Linux System Calls

Linux のシステムコールですが、下のサイトに詳細が出ています。全部で 338 種類もあるようです。

System Calls

簡単な足し算

次に簡単な足し算をしてみます。今度は、8ビットレジスタ al を使っています。システムコールも 64bit レジスタでなく本来の 32bit レジスタを使っています。また、前の例 (Hello World) ではリンカに直接 ld を使っていましたが、今度は gcc から間接的に使うようにしています。そのため、エントリーポイントの名前は C プログラムと同じ main に変えました。

長いので続く..

29
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
25