3

私の投稿の結果WindowsXPでint21hを使用して印刷できますか?、Windows APIの使用に関する記事を見ました。この記事では、_WriteConsole @4APIを使用してコンソールにメッセージを出力する方法について説明しました。記事はhttp://cs.lmu.edu/~ray/notes/x86assembly/にあります。

これまでの私のコードは次のとおりです。

.386P
.model  flat
extern  _ExitProcess@4:near
extern  _GetStdHandle@4:near
extern  _WriteConsoleA@20:near
public  _go

.data
      msg     byte    'if you get this, it worked.', 10
      handle  dword   ?
      written dword   ?
.code 
start:
_go:    
      push    -11
      call    _GetStdHandle@4
      mov     handle, eax
      push    0
      push    offset written
      push    13
      push    offset msg
      push    handle
      call    _WriteConsoleA@20
      push    0
      call    _ExitProcess@4
end start

私はこの構文を使用してコードをコンパイルしています:ML:

ml (the file is called test.asm) test.asm /c

リンク:

link test.obj C:\masm32\lib\kernel32.lib /SUBSYSTEM:CONSOLE /entry:go

コンパイルしてリンクするようになりましたが、生成された.exeを実行すると、エラーが返されることすらなく、まったく何も実行されません。コンソールは真っ黒です。どうしてこれなの?

どんな助けでも大歓迎です。そして、このフォーラムのユーザーには、毎日stackoverflow.comに攻撃を仕掛けたことをお詫びします。それは、学ぶためのリソースが非常に少ないということだけです。

前もって感謝します、

プログラム

4

3 に答える 3

3

まず、サンプルコードを取得しているリンクは、NASMユーザーからのものであり、彼はおそらく、彼の話し方からMASMを使用したことはありません。彼はまた、NASM形式のようにMASMサンプルを作成しています。アセンブリを使用するという事実は、高度なコンピュータユーザーである必要があることを意味します。バッチファイルの使い方やシステムパスの設定方法などを知っておく必要があります。何かがうまくいかないとき、あなたは研究することによって学びます。そのため、masm32rt.incが見つからないというエラーが表示されましたが、MASM32を使用しているとのことです。アセンブリにバッチファイルとIDEを使用しており、システムパスがMASM32のさまざまなディレクトリを指している。

masm32rt.incの前にmasm32\includeディレクトリへの絶対パスを追加します。そこにいる間に、テキストエディタでmasm32rt.incを開き、その内容を確認します-エラーが修正されました。

You start your source file with:
.586
.option casemap:NONE
.model flat, stdcall

include yourincludeshere and it could be a bunch
includelib yourlibshere same here a bunch

masm32rt.incにはすでにそれが含まれており、libsのincludeおよびincludelibと、広く使用されているincludeが含まれています。たくさんのタイピングを節約するために使用します。

ここで、\ masm32 \ includeのインクルードファイルを開きます。インクルードは、API呼び出しのプロトを設定するだけなので、パラメーターチェックにinvokeを使用できます。また、API呼び出しをエイリアス化するため、WriteConsoleAと入力する必要はありません。 WriteConsole地獄、あなたはYoConsole equを行うことさえでき、あなたのコードであなたはWriteConsoleのためにYoConsoleを書くでしょう。

そうは言っても、NASMのように-extern _WriteConsoleA @ 20:nearを使用することも、エントリラベルをパブリックに設定する必要もありません。MASMはこれによってエントリポイントを認識します。

.code
yourentrypointname:

end yourentrypointname

また、ソースでincludelibを使用しているため、リンカーにlibsを指定する必要はありません。

また、パラメータにハードコードされた数値を使用する習慣をつけないでください。今すぐその習慣から抜け出せ!Windowsヘッダーファイルは理由でDEFINESを使用します-コードの可読性、私たち(あなたを助ける人々)はそのAPI呼び出しに対して-11が何を意味するかを調べる必要はありません、私はdefineを使用しました、そしてあなたはそのパラメーターが何を意味するか知っています。さらに、WriteConsoleを40回呼び出すとどうなりますか?等式を使用する場合は、検索して置換するのではなく、等式だけを変更する必要があります。まともなMASMチュートリアルでIczelionを検索したい場合は、それらは古く、いくつかのエラーが含まれていますが、開始することができます。初期の私たちの多くは、これらのチュートリアルを使用していました。

于 2012-05-18T21:42:41.660 に答える
3

これは問題なく機能します。

include masm32rt.inc

.data
szMsg       db  "I am in the console!", 0
MSG_LEN     equ $ - szMsg

.data?
BytesWriten dd  ?

.code
start:
    push    STD_OUTPUT_HANDLE
    call    GetStdHandle

    push    NULL
    push    offset BytesWriten
    push    MSG_LEN
    push    offset szMsg
    push    eax
    call    WriteConsole

    push    0
    call    ExitProcess
end start

エントリラベルは_goですが、リンカーはgo-/ entry:goであるため、コンソールは作成されますが、コードは実行されません。この場合、エントリポイントをリンカに通知する必要はありません。エントリポイントは開始です...リンカはどのように認識しますか?エンドスタート

于 2012-05-18T03:14:04.893 に答える
1

MASM32を試すことができます。これは、コンソールアプリケーションのHelloWorldの例です。

; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««« *

    .486
    .model flat, stdcall
    option casemap :none   ; case sensitive

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc
    include \masm32\macros\macros.asm

    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib

    .code

start:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    print "Hello world"

    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start

ただし、現在のアセンブラを使い続けたい場合は、macros.asmの下に印刷マクロがあります。

print MACRO arg1:REQ,varname:VARARG      ;; display zero terminated string
    invoke StdOut,reparg(arg1)
  IFNB <varname>
    invoke StdOut,chr$(varname)
  ENDIF
ENDM

したがって、StdOutが必要です。MASM32では次のようになります。

StdOut proc lpszText:DWORD

    LOCAL hOutPut  :DWORD
    LOCAL bWritten :DWORD
    LOCAL sl       :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut, eax

    invoke StrLen,lpszText
    mov sl, eax

    invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut endp

したがって、この旅の終わりには、WriteConsoleではなくWriteFileを使用する必要があります:)

于 2012-05-17T13:20:37.537 に答える