アセンブラでWindowsのプログラムってどうやったらできるのかな? って思った。ずっと前にMASM32とか調べたら高機能マクロで簡単にできるよとか書いてあって、そんならCでやるわってなってから放置してた。

VS2017に付いてるml.exe(14.13.26132.0)の32ビット版でMessageBoxAを叩いて終わるだけのもの。これでも一応APIの呼び方は分かる。スタックに押し込んでAPIをコール。

msgbx.asm

.model	flat, stdcall

extern	MessageBoxA@16 : proc
extern	ExitProcess@4 : proc

public Start

.code
Start:
	push 40h
	push offset strCapt
	push offset strMsg
	push 0
	call MessageBoxA@16

	push eax
	call ExitProcess@4

.data
strCapt	db 'msgbx', 0
strMsg	db 'Hello World !', 0

end

アセンブルとリンクはml一行で完結。

ml msgbx.asm /link /subsystem:windows /Entry:Start kernel32.lib user32.lib

devenv.exe msgbx.exeでデバッグ。debugやsymdebと同じtやpやrコマンドが使える。

msgbx-devenv

64ビット版も作った。FASTCALL規約でAPIの引数がスタックではなくてレジスタを使う。

msgbx64.asm

extern	MessageBoxA : proc
extern	ExitProcess : proc

public	Start

.code
Start:
	sub rsp, 8h
	
	mov rcx, 0
	lea rdx, strMsg
	lea r8, strCapt
	mov r9, 40h
	call MessageBoxA

	mov ecx, 0
	call ExitProcess

.data
strCapt	db 'msgbx64', 0
strMsg	db 'Hello World !', 0

end
ml64 msgbx64.asm /link /subsystem:windows /entry:Start kernel32.lib user32.lib

ちゃんと確認してないので良くわからないが、APIへのコールは実際にはソースコードには明示されない記述したコードの後ろに暗黙に作られた最初のジャンプテーブル(callではなくjmp)を向いており、そこからリンカがくっつけたkernel32.lib、user32.libに含まれるAPI呼び出しコードへ引き継がれていく。それからライブラリに含まれる何十ステップものコードを経由した後、ローダが初期化したインポートテーブルを介してAPIが呼ばれるっぽい。面倒になってライブラリの内部は追いかけなかった。冒頭でMessageBoxAを叩いているなどと格好良く書いたが、本当はSDKのライブラリを呼んでいるだけ。アセンブラは闇が奥が深い。

広告

VS2017のml.exe、ml64.exeを使ってみる。” への1件のフィードバック

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中