x86 アセンブリを使用して、Windows 用の簡単なプログラム (コンソール入出力) を作成したいと考えています。誰かが私を正しい方向に向けることができれば、それは素晴らしいことです. いくつかの単純な x86 命令やレジスタの機能などについては、すでにかなりよく理解していますが、プログラムがオペレーティング システムとどのようにやり取りし、標準の入力と出力を使用するかについては謎のままです。これらのことは advapi32.dll や kernel32.dll などのライブラリと関係があること、およびコンパイラがこれらの動的にリンクされたライブラリを使用できるようにする静的ライブラリ .lib ファイルが関連付けられていることは知っていますが、それ以外は、これがどのように行われるのかほとんどわかりません起こります。C などの言語のヘッダー ファイルが .lib ファイルをどのように使用するかについては、私も曖昧です。
1 に答える
おそらく、いくつかの簡単なプログラムを作成するための指示を与え、そこから外挿させるのが最も簡単です。まず、いくつかのソースコードが必要です。
.386
.MODEL flat, stdcall
; This is what would come from a header -- a declaration of a the Windows function:
MessageBoxA PROTO near32 stdcall, window:dword, text:near32,
windowtitle:near32, style:dword
.stack 8192
.data
message db "Hello World!", 0
windowtitle db "Win32 Hello World.", 0
.code
main proc
invoke MessageBoxA, 0, near32 ptr message, near32 ptr windowtitle, 0
ret
main endp
end main
masm
それを構築するには、次のように呼び出します。
ml hello32.asm -link -subsystem:windows user32.lib
これは、ファイルをアセンブルするように指示し、リンクするときに、Windowsサブシステム用としてリンクするように指示し(主な代替手段は-subsystem:console
)、とリンクするように指示しuser32.lib
ます。後者は私たちにの定義を提供しますMessageBoxA
。
コンソールに書き込む同様のプログラムは、(奇妙なことに)もう少し複雑です。
.386
.MODEL flat, stdcall
getstdout = -11
WriteFile PROTO NEAR32 stdcall, \
handle:dword, \
buffer:ptr byte, \
bytes:dword, \
written: ptr dword, \
overlapped: ptr byte
GetStdHandle PROTO NEAR32, device:dword
ExitProcess PROTO NEAR32, exitcode:dword
.data
message db "Hello World!", 13, 10
msg_size dd $ - offset message
.data?
written dd ?
.code
main proc
invoke GetStdHandle, getstdout
invoke WriteFile, \
eax, \
offset message, \
msg_size, \
offset written, \
0
invoke ExitProcess, 0
main endp
end main
構築はほとんど同じですが、これはコンソールを使用するため、コンソールサブシステムを指定し、使用している関数はカーネルで定義されています。
ml hello_console.asm -link -subsystem:console kernel32.lib
ヘッダーには、、、、などについて上記MessageBoxA
で示した宣言と同等のものが含まれます。ただし、通常、各ヘッダーにはさらに多くの宣言が含まれます。たとえば、kernel32のすべての関数が単一のヘッダーに含まれる場合があります。GetStdHandle
WriteFile
ライブラリに関する限り、関係するメカニズムは多少関係していますが、ほとんど関係ありません。作業を完了するには、(たとえば)MSDNを調べて、ライブラリがリンクするように指示していることを確認し、コマンドラインに追加します。
より複雑な説明は、少なくとも静的ライブラリに対してリンクすると、呼び出した関数が検出され、それぞれのコピーが実行可能ファイル/DLLに配置されるというものです。(上記のように)DLL内のコードを使用している場合、基本的には、実行可能ファイルにレコードを入れて、どのDLLのどの機能に依存しているかを示します。次に、プログラムをロード/実行すると、ローダーはプログラムが依存するすべてのDLLを探し、それらをロードします(もちろん、依存するすべてのものを再帰的にロードします)。次に、ローダーがそれらの参照を修正するため、DLL内の関数への参照には、そのDLL内のその関数に割り当てられているアドレスが入力されます。