0

アセンブリが初めてなので、何が問題なのか教えてください。この問題を解決する方法がわかりません。

section    .text
    global _start   
_start:             
    mov edx,len     
    mov ecx,msg     
    mov ebx,1       
    mov eax,4       

    mov eax,1               

section .data
msg db 'Hello, world!', 0xa  ;
len equ $ - msg     ;
4

1 に答える 1

3

すでに述べたように、あなたのプログラムには明らかにシステムコールがありません。

Windows では (Windows 用の .EXE ファイルを生成する限り)、直接のシステム コールはありません。代わりに、Windows に付属の DLL で関数を呼び出す必要があります。

例:

mov ecx,len
push ecx
mov ecx,msg
push ecx
mov ecx,1
push ecx
call _write
add esp,12

32 ビット ウィンドウ (または 64 ビット ウィンドウで実行される 32 ビット プログラム) には、基本的に stdcall (= WINAPI、CALLBACK、PASCAL) と cdecl の 2 種類の関数があります。

どちらのタイプの関数でも、引数はスタック上にある必要があります (最初の引数は ESP+0、2 番目の引数は ESP+4 など)。例 "1" は最初のもので、"len" は最後のものです)。関数の結果 (存在する場合) は、EAX レジスタに返されます (浮動小数点値でない限り)。

次に、DLL で定義されている関数を呼び出します。最終的にその関数はシステム コールを実行しますが、このシステム コールはバージョン固有である可能性があります。あなたはそれを気にする必要はありません。

「stdcall」関数の場合、関数はスタックから引数を削除します。(wsprintf のような可変数の引数を持つ関数の場合、必須の引数のみが削除されます。) アセンブラーでは、そのような関数は次のように命名されます。

_Name@nnn

「名前」は C 言語で知られている関数の名前で、nnn はスタックから削除されるバイト数です。ほとんどの低レベル Windows 関数は stdcall 関数です。文字列を使用する関数は通常、ASCII を示す「A」または UNICODE 文字列を示す「W」で終わることに注意してください。通常、「A」バリアントを使用します。例: 関数「MessageBox」の呼び出し:

(push 4 arguments)
call _MessageBoxA@16

ほとんどの C 標準ライブラリ関数は「cdecl」です。上記の「write」の例を参照してください。Cdecl 関数はスタック ポインターを調整しないため、「call」命令の後に「add esp,nnn」を追加する必要があります。名前は、アンダースコアの後に C 関数名を追加することによって単純に形成されます (例: "write()" -> "call _write")。

于 2013-10-24T17:01:43.337 に答える