一番簡単な x64 アセンブリ言語プログラム (Windows, MASM)
固定値を返すだけの一番簡単な x64 アセンブリ言語プログラムを書いて、アセンブル・リンク・実行してみます。利用するアセンブラは Visual Studio に付属の 64bit 版 MASM(マイクロソフトマクロアセンブラ)です。
動作確認環境
- Windows 11 Home 22H2
- Visual Studio Community 2022 (MASM for x64)
6 行のアセンブリ言語プログラム
固定値 100 を返すだけの 6 行のシンプルなアセンブリ言語プログラムです。
.code
START PROC
mov eax, 100
ret
START ENDP
END
「.code」でコードセグメントの開始を示しています。ここから処理を書きます。ほかにもデータを記述する「.data」などがあります。
「START PROC ~ START ENDP」はプロシージャーの範囲を示しています。疑似言語で書くと「function START { ~ }」というイメージです。「START」は自分で決めた名前(ラベル)です。
「mov eax, 100」では、CPU の eax レジスタに 100 をセットしています。「eax = 100」のイメージです。eax の値がプログラムの終了コードになります。
「ret」は return の意味で、呼び出し元に戻ります。今回の呼び出し元は OS のモジュール、具体的には「kernel32.dll」です。
末尾の「END」はモジュールの終了を示しています。
「.code」の代わりに「_TEXT SEGMENT ~ _TEXT ENDS」と書くこともできます。こちらのほうが古い書き方です。
_TEXT SEGMENT
START PROC
mov eax, 100
ret
START ENDP
_TEXT ENDS
END
アセンブリ言語プログラムのビルド
コマンドラインからビルド(アセンブル+リンク)してみましょう。
Windows のスタートメニューから「x64 Native Tools Command Prompt for VS 2022」を選択します。
コマンドプロンプト (Terminal) が開きます。
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.1.3
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
C:\Program Files\Microsoft Visual Studio\2022\Community>
ソースファイルのあるディレクトリに移動します。
ここでは「c:\tmp」にあるものとします。
C:\Program Files\Microsoft Visual Studio\2022\Community> cd \tmp
C:\tmp>
64bit 版 MASM の実行ファイル名は「ml64.exe」です。
ml64 の引数にアセンブリ言語のソースファイル名と各種オプションを付けてビルドします。
C:\tmp> ml64 sample1.asm /link /subsystem:console /entry:START
Microsoft (R) Macro Assembler (x64) Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: sample1.asm
Microsoft (R) Incremental Linker Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
/OUT:sample1.exe
sample1.obj
/subsystem:console
/entry:START
「/link」以降のオプションは、アセンブラが内部的に呼び出すリンカー「link.exe」に対する指示です。「/subsystem:console」はコンソールプログラムの作成を、「/entry:START」はプログラムの起点を指示しています。「START」はアセンブリ言語プログラム内の「START PROC」に対応します。
ビルドにより、「sample1.exe」が生成されます。
アセンブルとリンクを別々に実行する場合は次のようにします。
C:\tmp> ml64 /c sample1.asm
Microsoft (R) Macro Assembler (x64) Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: sample1.asm
C:\tmp> link sample1.obj /subsystem:console /entry:START
Microsoft (R) Incremental Linker Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
ml64.exe のオプション「/c」が、アセンブルのみを行いリンクを行わないことを指示しています。アセンブルにより、オブジェクトファイル「sample1.obj」が生成されます。
その後、リンカーでリンクを行っています。最終的に生成されるのは、同じく「sample1.exe」です。
プログラムの実行
生成されたプログラムをコマンドプロンプトから実行し、終了コードを見てみます。
C:\tmp> sample1.exe
C:\tmp> echo %errorlevel%
100
期待通り「mov eax, 100」で設定した「100」が返ってきました。
なお、エクスプローラーからのダブルクリックで実行すると、一瞬コンソール画面が表示されますが、すぐに終了し、戻り値も確認できません。
Windows プログラムとしてビルド
コンソールプログラムではなく Windows プログラムとしてビルドする場合は、リンカーに「/subsystem:windows」を指定します。
C:\tmp> ml64 sample1.asm /link /subsystem:windows /entry:START
Microsoft (R) Macro Assembler (x64) Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: sample1.asm
Microsoft (R) Incremental Linker Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.
/OUT:sample1.exe
sample1.obj
/subsystem:windows
/entry:START
「Windows プログラム」といっても、ウィンドウが自動的に作られるわけではありません。コンソール画面が自動的に生成されることのない「非コンソールプログラム」と呼んだほうがいいかもしれません。
コマンドプロンプトから実行し、終了コードを見てみます。
C:\tmp> sample1.exe
C:\tmp> echo %errorlevel%
0
「100」ではなく「0」と表示されてしまいました。これは、コマンドプロンプトから Windows プログラムを実行するとプログラムの終了を待たずにプロンプトが返ってくるためです。
そこで、「start /wait」を利用してプログラムの終了を待つようにします。
C:\tmp> start /wait sample1.exe
C:\tmp> echo %errorlevel%
100
期待通り、「100」が返ってきました。
なお、エクスプローラーからのダブルクリックで実行すると、コンソール画面が生成されることもなく起動してすぐに終了するため、実行されたのだかされなかったのだかよくわからない状態になります。
おわりに
以上、x64 アセンブリ言語プログラムの作成・アセンブル・リンク・実行をしてみました。
次回はアセンブリ言語で、Windows API や C 言語のライブラリを呼び出す実行可能ファイル ( .exe)、静的ライブラリ (.lib)、動的ライブラリ (.dll) を作ってみます。
参考文献
[1] マイクロソフト「Microsoft Macro Assembler リファレンス」
https://learn.microsoft.com/ja-jp/cpp/assembler/masm/microsoft-macro-assembler-reference