540̲asm2023̲book.indb 1

2023/05/12 11:01

■サンプルファイルのダウンロードについて
本書掲載のサンプルファイルは、下記 URL からダウンロードできます。

https://-----------------------------------------

・本書の内容についてのご意見、ご質問は、お名前、ご連絡先を明記のうえ、小社出版部宛文書（郵送または E-mail）でお送りください。
・電話によるお問い合わせはお受けできません。
・本書の解説範囲を越える内容のご質問や、本書の内容と無関係なご質問にはお答えできません。
・匿名のフリーメールアドレスからのお問い合わせには返信しかねます。
本書で取り上げられているシステム名／製品名は、一般に開発各社の登録商標／商品名です。本書では、™ および ® マークは明記していません。本書に掲載されている団体／商品に対して、その商標権を侵害する意図は一切ありません。本書で紹介している URL や各サイトの内容は変更される場合があります。

540̲asm2023̲book.indb 2

2023/05/12 11:01

はじめに

近年においてソフトウェアエンジニアがハードウェアのアーキテクチャを意識する機会は激減しました。それは悪いことではないでしょう。ソフトウェアエンジニアがハードウェアを意識していては、開発したソフトウェアはハードウェア依存となりポータビリティやスケーラビリティなどを失ってしまいます。
ソフトウェアをアセンブリ言語で開発していた時代は遙か昔のこととなり、現在では C++ 言語などは言うにおよばす、仮想マシン上で動作する言語を利用する機会が多くなりました。より抽象化が進んだ環境を使用するようになったと言ってよいでしょう。つまり、現代のソフトウェア
エンジニアが、CPU の動作やアセンブリ言語を理解することが必要となる機会は減っています。
とはいえ、ソフトウェアエンジニアを自負するなら、基礎を習得することは重要です。基礎を理解していると、時代が移りインプリメント法やアーキテクチャが変わろうとも、新しい時代へ柔軟に対応できるでしょう。なぜならば、動作の表面だけを理解しているのではなくシステムの基本を理解しているからです。
本書の目的は、抽象化の進んだ言語のみを利用しているソフトウェアエンジニアに、アセンブ
リ言語を理解してもらうことです。その延長上で CPU 自体の動作についても、理解できるでしょう。アセンブリ言語をひととおり理解しようとすると大変な労力がかかり、必要に迫られていな
い限り途中で挫折するでしょう。そこで、本書はリファレンス的にアセンブリ命令のすべてを網羅して理解するのではなく、比較的簡単な命令を理解することによって、アセンブリ言語、ひいては CPU がどのようにプログラムを解釈実行するかを理解していただくことにつとめました。リ
ファレンスよりアプリケーションに重きを置き、興味を失わないように努めました。
リファレンスは用意しましたが、紙面の関係もあり十分でありません。アセンブリ命令を詳し
く知りたい人は、参考文献を参照してください。
本書の対象読者は，以下のような人を対象としています。
● 低水準言語が、どのようなものか体験したい人● アセンブリ言語を理解したい人● SIMD などベクトル処理を理解したい人

付録

iii

540̲asm2023̲book.indb 32023/05/12 11:01

是非、本書を参考に現代の CPU やアセンブリ言語の実際を理解し、コンピューターの基礎の理解や、高性能なプログラムの開発に役立ててください。微力ながら本書が学習の助けになれば幸いです。
謝辞
出版にあたり、お世話になった株式会社カットシステムの石塚勝敏氏に深く感謝いたします。
2023 年冬 都立東大和南公園にて 北山洋幸

iv

540̲asm2023̲book.indb 42023/05/12 11:01

本書の使用にあたって
開発環境、および、実行環境を説明します。
● プラットフォーム

Windows 10 Home を開発・実行環境とします。一部のプログラムは、Ubuntu 22.04.1 LTS、Windows 10 Pro でも確認しています。
● オペレーティングシステムのビット

主に 64 ビット Windows を使用します。いくつかのプログラムは、Ubuntu 20.04.2 LTS で確認しました。
● コンパイラー

Windows では、無償の Visual Studio Community 2022 を使用します。Ubuntu では、
g++ バー
ジョン 11.3.0、clang++ バージョン 14.0.0-1ubuntu1 を利用しました。
● CPU

最新の命令を使用しているプログラムは、比較的古い CPU が搭載されたパソコンでは直接実行できません。ただ、エミュレーターが提供されていますので、速度は若干低下しますが、古いパソコンであっても動作させるのは可能です。
● エミュレーター

自 身 の 環 境 が 最 新 の 命 令 を 使 用 で き る CPU で な い 場 合、Intel Software Development
Emulator（Intel SDE）を利用してください。これについては、付録 A で詳しく解説します。
● URL

URL の記載がある場合、執筆時点のものであり変更される可能性もあります。リンク先が存在しない場合、キーワードなどから自分で検索してください。
● バイト、ワード、ダブルワード、クワッドワード

バイトは 8 ビット（1 バイト）
、ワードは 16 ビット（2 バイト）
、ダブルワードは 32 ビット（4バイト）、クワッドワードは 64 ビット（8 バイト）です。高級言語では使用しませんが、ア
センブリ言語を記述する場合、このような表現が使用されます。
● アドレスあるオブジェクトが格納されているメモリー位置のことです。
付録v

540̲asm2023̲book.indb 52023/05/12 11:01

● アセンブリ言語

プログラミング言語の一つで、コンピューターが直接解釈・実行できるマシン語と 1 対 1 に対応した言語です。いわゆる低水準言語（低級言語 ) の代表です。アセンブリ言語はマシン
語の命令と 1 対 1 に対応するニーモニック（英単語）などを使い記述します。現在では、抽象化された高水準言語が主流ですが、CPU 性能を限界まで引き出すチューニングを行いたい
場合や、組み込みソフトウェアの開発などハードウェアに近い分野の開発などでは、今でも使われています。
● アセンブラー

アセンブリ言語で記述されたソースコードを、コンピューターが解釈できるマシン語へ翻訳するソフトウェアのことです。C++ 言語などに対するコンパイラーと同じ位置付けです。
● カタカナ語の長音表記「メモリー」や「フォルダー」など、最近は語尾の「ー」を付けるのが一般的になっています。
なるべく、最近の表現に合わせましたが統一していません。
● ソースリストとソースコード

基本的に同じものを指しますが、ソースリストと表現する場合はソース全体を、ソースコー
ドと表現する場合はソースの一部を指す場合が多いです。
● 命令やレジスター名

SIMD 命令やレジスター名の表現で、大文字と小文字の表現が混在します。例えば、ZMM1 とzmm1、そして vmovdqa64 と VMOVDQA64 は同じものです。
● Linux と Ubuntu

Linux と Ubuntu を混在して使用していますが、本書のプログラムを動作させたのは、すべてUbuntu 上のみです。ただ、Ubuntu に限らず Unix（Linux）系と説明したほうが良さそうな場合は、Linux を用います。
● AVX-512 と AVX512

AVX512 と記述する場合と、AVX-512 と記述する場合がありますが同じものを指します。
● BOM コード

サンプルのソースファイルは BOM コードが付与されているときがあります。一般的に BOM
コードの有無は処理に影響しませんが、まれに BOM コードを意識しない環境があり、正常にファイルを扱えないときがあります。そのような場合は BOM コードを削除してください。
BOM コードはファイルの先頭に格納されています。

vi

540̲asm2023̲book.indb 62023/05/12 11:01

目

次

目次

はじめに...................................................................................................................................... iii

第1章

はじめてのアセンブリ言語.......................................... 1

1.1 Windows の例................................................................................................. 1
1.1.1

命令の解説......................................................................................................................2

1.2 Ubuntu の例.................................................................................................... 4
1.2.1

ビルドと実行..................................................................................................................4

1.3 64 ビット.......................................................................................................... 6
1.3.1
1.3.2
1.3.3
1.3.4

第2章

インラインアセンブラが使えない.........................................................................6
ファイル構成..................................................................................................................6
アセンブリ言語で関数を作る..................................................................................8
Ubuntu...........................................................................................................................10

アセンブラプログラミングの基礎 .............................. 13

2.1 x64 のレジスター群.......................................................................................13
2.1.1
2.1.2

汎用レジスター一覧.................................................................................................15
SIMD レジスター一覧..............................................................................................16

2.2 呼び出し規約...................................................................................................16
2.2.1
2.2.2

引数と戻り値...............................................................................................................17
保護する必要のあるレジスター...........................................................................18

2.3 簡単な具体例...................................................................................................19
2.3.1
2.3.2
2.3.3
2.3.4
2.3.5

変数の代入...................................................................................................................19
変数のサイズ...............................................................................................................21
ptr 演算子.....................................................................................................................23
配列へアクセス..........................................................................................................25
戻り値の例...................................................................................................................27

2.4 レジスターの保護............................................................................................28
2.4.1 破壊して良いレジスターへ退避...........................................................................28
2.4.2 汎用レジスターを push や pop で保護.............................................................29
2.4.3 SIMD レジスターの保護.........................................................................................30
2.4.4 マクロ化と zmm レジスター................................................................................33

2.5 作業領域...........................................................................................................35
2.6.1

付録

2.6 戻り値..............................................................................................................38
戻り値が char ............................................................................................................38vii

540̲asm2023̲book.indb 72023/05/12 11:01

2.6.2
2.6.3
2.6.4
2.6.5
2.6.6

戻り値が short............................................................................................................38
戻り値が int.................................................................................................................39
戻り値がポインター.................................................................................................40
戻り値が単精度浮動小数点....................................................................................41
戻り値が倍精度浮動小数点....................................................................................41

2.7 命令の解説.......................................................................................................42

第3章

算術命令 ................................................................. 45

3.1 整数の加減乗除算............................................................................................45
3.1.1

命令の解説...................................................................................................................50

3.2 実数の加減乗除算............................................................................................53
3.2.1

倍精度浮動小数点......................................................................................................55

3.3 Ubuntu でのビルドと実行............................................................................56
3.3.1

第4章

命令の解説...................................................................................................................59

論理命令 ................................................................. 63

4.1 論理積と論理和................................................................................................63
4.2 排他的論理和...................................................................................................65
4.3 命令の解説.......................................................................................................66

第5章

シフトと回転命令 .................................................... 69

5.1 左シフト...........................................................................................................69
5.2 右シフト...........................................................................................................72
5.3 回転（ローテート）..........................................................................................75
5.4 命令の解説.......................................................................................................80

第6章

制御命令 ................................................................. 83

6.1 無条件ジャンプ................................................................................................83
6.2 条件ジャンプ・等しいか.................................................................................84
6.2.1

EFLAGS レジスター..................................................................................................86

6.3 条件ジャンプ・大小比較.................................................................................88
6.4 繰り返し...........................................................................................................90viii

540̲asm2023̲book.indb 82023/05/12 11:01

目 次

6.5 繰り返しで一次元配列を加工.........................................................................91
6.6 命令の解説.......................................................................................................92
6.6.1

第7章

ジャンプ命令の一覧表.............................................................................................95

簡単な応用.............................................................. 97

7.1 ビット操作.......................................................................................................97
7.1.1
7.1.2
7.1.3
7.1.4
7.1.5
7.1.6
7.1.7

ビット並び反転..........................................................................................................97
ビット値取得............................................................................................................ 103
ビットセット............................................................................................................ 104
ビットリセット....................................................................................................... 106
ビット反転................................................................................................................ 107
オンビットをカウント.......................................................................................... 108
マスクビットパターン生成................................................................................. 110

7.2 文字列操作.................................................................................................... 112
7.2.1
7.2.2
7.2.3
7.2.4
7.2.5
7.2.6
7.2.7
7.2.8

英大文字を小文字へ変換..................................................................................... 112
英小文字を大文字へ変換..................................................................................... 115
文字列長を求める................................................................................................... 116
文字の並びを逆転................................................................................................... 118
文字列を暗号化....................................................................................................... 122
strcpy 互換................................................................................................................ 123
strcmp 互換............................................................................................................... 124
命令の解説................................................................................................................ 126

7.3 メモリー操作................................................................................................ 129
7.3.1
7.3.2

第8章

メモリーのコピー................................................................................................... 129
memcmp 互換.......................................................................................................... 131

配列 ..................................................................... 135

8.1 スカラー加算................................................................................................ 135
8.1.1
8.1.2

Ubuntu でのビルドと実行.................................................................................. 139
イントリンシック版.............................................................................................. 142

8.2 総和............................................................................................................... 145
8.3 最小値........................................................................................................... 150
8.3.1

最小値とその位置................................................................................................... 155

8.4 最大値........................................................................................................... 159
8.5 reduce........................................................................................................ 162
和................................................................................................................................... 162
最小値.......................................................................................................................... 166
最大値.......................................................................................................................... 168
AVX 命令を使った関数......................................................................................... 170

付録

8.5.1
8.5.2
8.5.3
8.5.4

ix

540̲asm2023̲book.indb 92023/05/12 11:01

8.6 配列同士の加算............................................................................................. 172
8.6.1

Ubuntu でのビルドと実行.................................................................................. 176

8.7 配列同士の飽和加算..................................................................................... 178
8.7.1

Ubuntu でのビルドと実行.................................................................................. 181

8.8 SIMD 命令とメモリーアライン.................................................................. 182
8.8.1
8.8.2
8.8.3
8.8.4
8.8.5

アライメント............................................................................................................ 182
メモリーの動的割付.............................................................................................. 183
ポータビリティ....................................................................................................... 185
割り込みが発生する具体例................................................................................. 186
マスクレジスターとデータ長............................................................................ 197

8.9 命令の解説.................................................................................................... 200

第9章

予測と分岐............................................................ 215

9.1 値設定........................................................................................................... 215
9.1.1

Ubuntu でのビルドと実行.................................................................................. 220

9.2 乗算............................................................................................................... 222
9.3 下限............................................................................................................... 224
9.4 上限............................................................................................................... 230
9.5 範囲............................................................................................................... 234
9.6 命令の解説.................................................................................................... 238

第 10 章抽出 ................................................................... 241

10.1 小さな値........................................................................................................ 241
10.2 大きな値........................................................................................................ 246
10.3 範囲............................................................................................................... 248
10.3.1

最小値とその位置................................................................................................ 250

10.4 命令の解説.................................................................................................... 253

第 11 章正規化 ................................................................ 255

11.1 AOS と SOA............................................................................................... 255
11.2 3D の X 座標・gather/scatter 編.......................................................... 257
11.3 3D の X 座標・compress/expand 編................................................... 264
11.4 AOS と SOA の相互変換・gather/scatter 編...................................... 268x540̲asm2023̲book.indb 102023/05/12 11:01

目 次

11.5 AOS と SOA の相互変換・compress/expand 編............................... 275
11.6 座標の平行移動............................................................................................. 280
11.6.1

Ubuntu でのビルドと実行................................................................................ 282

11.7 命令の解説.................................................................................................... 285

第 12 章移動平均 ............................................................. 289

12.1 単純移動平均................................................................................................ 289
12.2 共通プログラム............................................................................................. 294
12.2.1

Ubuntu でのビルドと実行................................................................................ 298

12.3 加重移動平均................................................................................................ 299
12.3.112.3.2

単純移動平均......................................................................................................... 306
係数を使った加重移動平均.............................................................................. 306

12.4 命令の解説.................................................................................................... 307

付 録 ................................................................................ 309
付録 A CPU エミュレーター................................................................................... 309
付録 B プロジェクト作成（Visual Studio）......................................................... 322
付録 C プロジェクト作成（Ubuntu）.................................................................... 327
付録 D 係数生成........................................................................................................ 335

参考文献、参考サイト、参考資料........................................................................................ 341
索  引...................................................................................................................................... 343

付録

xi

540̲asm2023̲book.indb 11

2023/05/12 11:01

540̲asm2023̲book.indb 122023/05/12 11:01

第1章

はじめての
アセンブリ言語第1章

1

はじめてのアセンブリ言語

早速ですが、簡単な代入をアセンブリ言語で記述してみましょう。本書は主に、Windows のVisual Studio に付属する ml64 や cl コマンドを利用します。もちろん、Visual Studio のプロジェ
クトからビルドしても構いません。これに加え、Linux 系 OS（Ubuntu）の g++ や clang++ のイン
ラインアセンブラーを利用する方法も解説します。

1.1 Windows の例
まず、Windows の例を示します。以降に、ソースリストを示します。
リスト1.1●mov.cpp（01begin）#include <iostream>
int main(void){

int a = 0;__asm

mov a, 1

std::cout << "a = " << a << std::endl;}

return 0;

1

540̲asm2023̲book.indb 1

2023/05/12 11:01

1

はじめてのアセンブリ言語

C++ 言語内にアセンブリ言語の記述を行う場合、インラインアセンブラを使用すると簡単です。

この例では、__asm キーワードに続きアセンブラコードを記述します。mov 命令はデータを移動する命令です。__asm に続き、アセンブラコードを記述しますが、コードの最後にセミコロンは必要ありません。本プログラムは、1 を変数 a へ格納します。このプログラムの実行結果を示します。
a = 1

この例ではアセンブリ命令が一つだけですので、__asm キーワードに続けてすぐにその命令を記述できます。複数のアセンブリ命令を記述したい場合は、それらを {} でくくったものを __asm

キーワードに続けて記述します。もちろん、命令が一つだけであっても {} で囲んで構いません。

次の二つはどちらも a に 1 を代入します。
__asm

mov a, 1

__asm
{
}

mov a, 1

mov 命令の構文を参照すると分かりますが、ソースが 1 でデスティネーションが a です。つまり、

変数 a に 1 が代入されます。

1.1.1 命令の解説
mov 命令mov 命令を簡単に説明します。名前から類推できるように、mov 命令は、データ転送命令です。

8 ビット、16 ビット、または 32 ビット（64 ビットモードでは 64 ビット）のデータを CPU のレジスター同士、メモリーと即値、あるいはレジスターとメモリーの間で移動する命令です。
ニーモニックmov デスティネーションオペランド, ソースオペランド

ニーモニックには、Intel 形式と ATT 形式があり、記述方法やオペランド位置に違いがあります。どちらかを理解してしまえば、別のニーモニックを記述するのに苦労しません。ただし、転送元と転送先が逆になるためケアレスミスを起こしやすくなるでしょう。本書では主に Intel 形式のニーモニックを採用します。

2

540̲asm2023̲book.indb 2

2023/05/12 11:01

1.1

Windows の例

1

ニーモニック
基本的にプログラム内ではアセンブリ命令のニーモニックは小文字入力します。ニー

2

モニックは、大文字でも小文字でも構いません。

3
ビルドと実行4

簡単なプログラムなので、プロジェクトは作成せず、Visual Studio をインストールすると同時5に使用できるようになる「x86 Native Tools Command Prompt for VS 2022」を使ってビルドします。ビルドと実行の例を次に示します（コマンドラインに入力した部分を太字で示します）。

6

C:¥>cl /EHsc mov.cpp

7

Microsoft(R) C/C++ Optimizing Compiler Version xx.xx.xxxxx for x86
Copyright (C) Microsoft Corporation.

All rights reserved.

8

mov.cpp

Microsoft (R) Incremental Linker Version xx.xx.xxxxx.x

9/out:mov.exe

10C:¥>mov

11

Copyright (C) Microsoft Corporation.

All rights reserved.

mov.obj
a = 1

12

付録

3

540̲asm2023̲book.indb 32023/05/12 11:01

1

はじめてのアセンブリ言語

1.2 Ubuntu の例
前節の Windows 用のプログラム（リスト 1.1）を Ubuntu 用に書き直します。ソースリストは
次のようになります。
リスト1.2●movGpp.cpp（01begin）#include <iostream>
int main(void){

int a = 0;__asm__ __volatile__ ("movl $1, %0¥n": "=r" (a));
std::cout << "a = " << a << std::endl;}

return 0;__asm__（または asm）はインラインアセンブラを使用することを示します。続く __volatile__（または volatile）は省略可能ですが、そうすると内容によってはアセンブリ言語で記述した部分

が最適化対象となってしまいます。アセンブリ言語で記述したコードを確実に実行させたいなら、__volatile__ を指定するのが適切でしょう。

1.2.1 ビルドと実行
gcc（g++）では、コンパイルオプションを指定しない限り、Intel 形式ではなく AT&T 形式を用います。Intel 形式と AT&T 形式では、オペランドの並び順が逆になります。インテル社のマニュアル類は当然 Intel 形式で記述されているため、混乱しないように注意してください。
以降に、ビルドと実行の例を示します（太字は入力した部分です）。
$ g++ movGpp.cpp$ ./a.outa = 1

4

540̲asm2023̲book.indb 42023/05/12 11:01

1.2

Ubuntu の例

g++ で Intel 形式

1

gcc（g++）にコンパイルオプションを指定すると、Intel 形式で記述できます。Intel 形式で記述
したソースリストを次に示します。

2

リスト1.3●movGppIntel.cpp（01begin）

3#include <iostream>4

int main(void){

int a = 0;5__asm__ __volatile__ ("mov %0, 1¥n": "=r" (a));

6

std::cout << "a = " << a << std::endl;}

7

return 0;

8

命令が Intel 形式になるとともに、オペランドの位置も Intel 形式となります。Visual Studio、

9

g++、そして clang++ などを併用する場合は、Intel 形式で記述する方が混乱は起きないでしょう。
ビルドと実行の例を次に示します。Intel 形式で記述したときは、コンパイルオプションに

10-masm=intel を指定してください。

11$ g++ -masm=intel movGppIntel.cpp$ ./a.out

12

a = 1

clang++
コンパイラーを g++ から clang++ へ変更したときのビルドと実行の例も示します。
$ clang++ movGpp.cpp$ ./a.out
a = 1$ clang++ -masm=intel movGppIntel.cpp
付録$ ./a.outa = 1

5

540̲asm2023̲book.indb 52023/05/12 11:01

1

はじめてのアセンブリ言語

1.3 64 ビット
Windows の 64 ビット対応プログラムを作成する場合、C++ 言語内にインラインアセンブラを記述できません。ここでは、Windows における、64 ビットのアセンブリ言語を解説します。ア
センブリ言語の記法は、使用するプロセッサー、オペレーティングシステム、そしてコンパイ
ラーやアセンブラーに依存します。本書は、環境や記法の説明を目的としておらず、アセンブリ
言語へフォーカスしたいため、一つの環境に絞って解説します。一つの環境でアセンブリ言語を理解できれば、異なる環境に適合させるのは容易です。プロセッサーが異なる場合は若干困難が伴うでしょうが、基本的な考えを理解しておけばそれほど苦にはなりません。Linux 上で C++ を理解した人が Windows 上の C# を理解するのに大きな困難を伴わないのと同様です。
これ以降は、Windows の 64 ビット環境をメインに解説します。ただ、いくつかの例では g++などの解説も行います。g++ などはアセンブリ言語をインラインで記述できるため、本節で解説する呼び出し規約やレジスター保護に注意する必要はありません。ただその反面、記述法が少し面倒で、破壊するレジスターを明示的にコンパイラーに知らせる必要があります。

1.3.1 インラインアセンブラが使えない
Visual Studio を使用する場合、プラットフォームに x64 を選ぶとインラインアセンブラを使用することはできません。理由はスタックやレジスターの管理など、いろいろあるのでしょう。イ
ンラインアセンブラを使用できないため、アセンブリコードは別のファイルに単独で記述しなけ
ればなりません。以降では簡単な例を挙げて、64 ビット環境で記述するときの手順を示します。

1.3.2 ファイル構成
これまでのプログラムのソースファイルは一つでした。ところが、64 ビットでは C++ 言語ファ
イル中にアセンブリコードを記述できないため、アセンブリコードを記述したファイルが、もう一つ必要です。ファイルとコンパイラーやアセンブラーの概念図を次に示します。

6540̲asm2023̲book.indb 62023/05/12 11:01

1.3

64 ビットC/C++ 言語で記述したソースファイル

アセンブリ言語で記述したソースファイル1

コンパイラー

アセンブラー2

オブジェクトファイル

オブジェクトファイル

3

リンカー

4

実行形式ファイル

5

図1.1●ファイルとコンパイラーやアセンブラーの関係

Visual Studio の統合環境を利用する場合は、プロジェクトに含まれるソースファイルは自動的6にコンパイラーもしくはアセンブラーによって翻訳されます。リンカーなども自動で起動されますので、C++ 言語で記述したファイルと、アセンブリ言語で記述したファイルが混在しても、単7にビルドを選択するだけです。ビルドに関しては、C++ 言語で記述したファイルのみで構成されたプロジェクトと何ら変わりません。ただし、プロジェクトの設定を少し変更する必要がありま8す。これについては付録で解説します。

9

プロジェクト10

C/C++ 言語で記述したソースファイル

アセンブリ言語で記述したソースファイル

コンパイラー

アセンブラー

リンカー

11
12

意識する必要なし

実行形式ファイル

図1.2●Visual Studioプロジェクトのファイル関係付録

7

540̲asm2023̲book.indb 72023/05/12 11:01

1

はじめてのアセンブリ言語

1.3.3 アセンブリ言語で関数を作る
以降に、C++ 言語で記述したソースリストとアセンブリ言語で記述したソースリストを示します。
リスト1.4●movRegister64.cpp（01begin）#include <iostream>#include <iomanip>

extern "C" void asmCode(char* ca, short* sa, int* ia);using namespace std;
int main(void){char ca = 0;

short sa = 0;
int ia = 0;

asmCode(&ca, &sa, &ia);cout << hex << uppercase << setfill('0') << right;

cout << "ca = 0x" << setw(2) << (unsigned int)ca << endl;
cout << "sa = 0x" << setw(4) << (unsigned int)sa << endl;
cout << "ia = 0x" << setw(8) << (unsigned int)ia << endl;
return 0;}

char 型変数 ca、short 型変数 sa、そして int 型変数 ia へ値を設定する簡単なプログラムです。

リスト1.5●movRegister64Asm.asm（01begin）
;

; rcx

= &ca

; r8

= &ia

; rdx

= &sa

;asmCode(&ca, &sa, &ia);
;

_TEXT

segment
public asmCode

8

540̲asm2023̲book.indb 82023/05/12 11:01

1.3

align

64 ビット16

asmCode proc
moveax, 01020304h

movword ptr [rdx], ax

mov
mov
ret

byte ptr [rcx], al1; eax=0x01020304

2dword ptr [r8], eax

3

asmCode endp
_TEXT

4

ends
end

5

rcx レジスターに ca のアドレス、rdx レジスターに sa のアドレス、そして r8 レジスターに ia

6のアドレスが渡されます。まず、eax レジスターに 01020304（16 進数）を設定します。そして、ca に al レジスターを、sa に ax レジスターを、そして ia に eax レジスターの値を代入します。

7
8

このプログラムのビルドと実行の例を示します。簡単なプログラムなので、プロジェクトは作成せず、Visual Studio をインストールすると同時に使用できるようになる「x64 Native Tools

9

Command Prompt for VS 2022」を使ってビルドします。Visual Studio をインストールしていても C++ の環境をインストールしていない場合、「x64 Native Tools Command Prompt for VS 2022」

10は現れません。そのようなときは、Visual Studio に「C++ によるデスクトップ開発」も追加イン
ストールしてください。このプロンプトを使ってビルドすると、64 ビットでビルドされます。

11C:¥>ml64 /c movRegister64Asm.asm
Microsoft (R) …

12…

C:¥>cl /O2 /EHsc movRegister64.cpp movRegister64Asm.obj…

C:¥>movRegister64
ca = 0x04

sa = 0x0304

ia = 0x01020304

当然ですが、64 ビット対応のビルド環境ではインラインアセンブラを記述できませんので、以付録

前紹介した方法でプログラムを記述するとエラーが発生します。

9540̲asm2023̲book.indb 92023/05/12 11:01

1

はじめてのアセンブリ言語

1.3.4 Ubuntu
簡単なプログラムですので、Ubuntu の g++ や clang++ 用のソースリストも示します。Visual
Studio と違い、g++ などでは 64 ビット対応のプログラムもインラインでアセンブリ言語を記述できます。
リスト1.6●movRegister01gpp.cpp（01begin）#include <iostream>#include <iomanip>

using namespace std;
int main(void){char ca = 0;

short sa = 0;
int ia = 0;__asm__ __volatile__ ("movl $0x01020304, %%eax¥n""movb %%al,"movw %%ax,

%0¥n"
%1¥n"

"movl %%eax, %2¥n": "=r" (ca), "=r" (sa), "=r" (ia):: "%eax");

cout << hex << uppercase << setfill('0') << right;

cout << "ca = 0x" << setw(2) << (unsigned int)ca << endl;
cout << "sa = 0x" << setw(4) << (unsigned int)sa << endl;
cout << "ia = 0x" << setw(8) << (unsigned int)ia << endl;}

return 0;

ビルドと実行の例を次に示します。

10540̲asm2023̲book.indb 102023/05/12 11:01