パープルハット

※当サイトではGoogleアドセンス広告を利用しています

アセンブラ(Linux) 環境構築とHelloWorldの表示


概要

  • 最近アセンブラを始めてHelloWorldを出力したのですが、いろいろ難しかったので備忘録としてまとめました。
  • 初学者なので、解説はちょいちょい間違ってるかもしれないです。



使用した環境など

OS Ubuntu22.04
CPU Intel 64-bit



準備

  • 以下のコマンドを実行して、必要なものをインストールします。
  • アセンブリ言語を翻訳してくれるアセンブラはnasmにしました。
sudo apt-get install nasm
sudo apt install binutils



Hello Worldを表示する

1. ASMファイルの用意

  • アセンブリ言語は拡張子asmのファイルに記述します。
  • 以下のコードを用意し、「hello.asm」に記述しました(コードの解説は後述)。

section .data
	message: db 'Hello World!', 10

section .text
	global _start

_start:
	mov rax, 1 
	mov rdi, 1
	mov rsi, message
	mov rdx, 13
	syscall;
	
	mov rax, 60
	xor rdi, rdi
	syscall




2. 実行ファイルの生成

作成した「hello.asm」を実行するために、次の2つのコマンドを実行します。

nasm -f elf64 hello.asm
ld -o hello hello.o


正しく実行できると、「hello.o」と「hello」と2つのファイルが生成できます。
ファイル構成



3. 実行ファイルを動かす

以下のコマンドで生成したファイルを実行させます。

./hello


すると、以下の様に「Hello World!」が出力されます。

Hello World!





ソースコードの解説(行ごと)

section .data

ここにはプログラムで使用する変数を格納します。

message: db 'Hello World!', 10

message 定義したい変数名
db
'Hello World!', 10
  • 変数に格納するデータです。
  • カンマにより、「Hello World!」と「10(改行コード)」を連結させています。



section .text

とりあえずスルーでOKです。


_start:

プログラムのメインとなる部分を記述します。

mov rax, 1

  • movはメモリやレジスタに値を書き込む処理であり、この行ではraxというレジスタに1という値を書き込んでいます。
  • raxには命令の種類(システムコール番号)を指定するレジスタだそうです。1を指定すると出力が行えるようになります。
  • このシステムコール番号はCPUにより異なるそうですが、本環境における代表的なものを以下に示します。
番号 処理
1 出力
2 ファイルを開く
60 プログラムを終了させる

参考:Syscall Number for x86-64 linux (A)

補足(1):出力(システムコール番号1)について

ssize_t write(int fd, const void *buf, size_t count);

の処理を行います。引数の意味を下の表に示します。

名称 意味
fd
  • ファイルディスクリプタ(書き込み先のファイルまたはデバイスを指定)
  • 1を指定すると標準出力になるみたいです。
buf
  • 書き込むデータが格納されたバッファへのポインタ。
  • とりあえず、表示したい文字を渡せばよいみたいです。
count 表示したい文字数


補足(2):引数の指定

  • 関数に渡すのではなく、引数に該当するレジスタに書き込む必要があるそうです。
  • 引数の番号と対応するレジスタを以下に示します。
引数の番号 対応するレジスタ名
1 rdi
2 rsi
3 rdx
4 r10
5 r8
6 r9

参考:Syscall Number for x86-64 linux (A)

実際に引数を指定

  • 補足(1)、(2)を基に出力のための引数の指定を行います。
引数 レジスタ 意味
fd rdi 1 標準出力を行う
buf rsi message 表示したい文字列が変数「message」に格納された「Hello World!」であることを伝える
count rdx 13
  • 13文字で表示したいことを伝える(改行文字も含む)
  • 注)例えば3を指定すると表示は「Hel」になります


ソースコードの各行と上の表の対応を確認してみてください。

mov rdi, 1
mov rsi, message
mov rdx, 13


syscall;

  • ここまでの処理を実行させるので、「Hello World!」が表示できます。


mov rax, 60

  • このシステムコール番号60を指定する。
  • 先程の表より、プログラムを終了しようとしていることが分かる。


xor rdi, rdi

  • rdiとrdiの排他的論理和を取ることで、rdiの中身を0に初期化します。


syscall;

  • ここまでの処理を実行し、プログラムを終了させる。