0

私はこの問題で 1 か月苦しんできましたが、もうあきらめようとしています。これは単純なプログラムであり、なぜ正しく動作しないのかわかりません。そこで、私が作成しようとしているのは、コマンド ラインを解析し、実行可能ファイルへのフル パスである最初の引数を表示する単純なアプリケーションです。これは私のコードがどのように見えるかです:

use32

[EXTERN GetStdHandle]
[EXTERN GetCommandLineW]
[EXTERN WriteConsoleW]
[EXTERN ExitProcess]

[section .bss]
StdHandle resd 1
PathStart resw 1
PathEnd resw 1
WrittenChars resw 1

[section .data]
message db __utf16__("Hello everybody"), 13, 10, 0

[section .text]
global start

start:
    call GetHandler
    call GetCommandLine
    end:
        mov eax, 0
        ret

    GetHandler:
        push -11
        call GetStdHandle
        cmp eax, 1
        push ebx
        mov ebx, 1
        jl CloseApp
        pop ebx
        mov dword[StdHandle], eax
        ret

    GetCommandLine:
        cld
        call GetCommandLineW ; UNICODE
        mov esi, eax
        mov bh, 0 ; here we save the argc
        mov ecx, eax ; here we save the pointer of the first arg

        Parse:
            lodsw
            cmp ax, __utf16__(' ')
            je NewArg
            jmp ContinueParsing

            NewArg:
                inc bh
                cmp bh, 1
                jne Parse
                ; if the first arg was just read save the 
                ; start from ecx and end from esi to the BSS variables
                mov dword[PathStart], ecx
                mov dword[PathEnd], esi
                jmp ShowPath

        ContinueParsing:
            cmp ax, 0
            jne Parse

        ShowPath:
            mov ecx, [PathEnd]
            mov ebx, [PathStart]
            sub ecx, ebx ; text size
            shr ecx, 1 ; is UNICODE
            push dword[PathStart]
            push dword[ecx]
            call ShowText
            ret

    ShowText:
        push ebp
        mov ebp, esp
        push 0
        push dword WrittenChars
        push dword [ebp+8]
        push dword [ebp+12]
        push dword [StdHandle]
        call WriteConsoleW
        pop ebp
        ret 8

    CloseApp:
        push ebx
        call ExitProcess
        pop ebx
        ret

うーん、スペルを間違えたり何かを見逃したりしたかもしれませんが、それは問題ではありません。コードは正常にコンパイルおよびビルドされますが、表示されるメッセージは実行可能ファイルの名前のみであり、予想されるフル パスではありません。フルパスが"D:\My Projects\NASM\Demo.exe"の場合、 "Demo"しか表示されません。呼び出す前ShowTextに変数の引数を準備すると、messageそれは機能し、テキストを正しく表示できるので、問題はポインターとフルパスの長さを正しく取得することにあると思います。それでも、OllyDbgを使用してアプリケーションの実行を調べると、セクションに正しい値が格納されていることがわかりますBSS。これは非常に奇妙で、目の良い人なら原因を突き止めることができるかもしれません。前もって感謝します

更新 今日、私は次のようにコマンドライン全体を表示しようとしました:

GetCommandLine:
        cld
        call GetCommandLineW ; UNICODE
        mov esi, eax
        ; display it here
        push    dword       eax
        push    dword       128
        call    ShowText

そして、私はまだ奇妙なキャラクターを見ます。代替手段があることは知っていますが、一見しただけで簡単に機能しない理由を知りたいだけです。つまり、コンピューターは無作為に説明なしに物事を行うわけではありません。

4

1 に答える 1

1

jne Parse ; Otherwise, continue parsing
mov dword [PathStart], ecx ; Save the start of the path's string
mov dword [PathEnd], esi ; Save the end of the path's string
ContinueParsing:
cmp ax, 0 ; If this is not the end of the command-line
jne Parse ; go back to Parse

mov dword [PathEnd], esiする必要jmpがあります後ShowPath。それ以外の場合は、最終的に if をチェックするax == 0ことになります (スペース文字が含まれているため、明らかにそうではありません) Parse


mov ecx, [PathStart] ; Save the start of the path's string in ECX
mov ebx, [PathEnd] ; Save the end of the path's string in EBX
sub ecx, ebx ; Calculate the size of the path's string in ECX

PathEndから差し引いていPathStartます。それは逆であるべきです。shr ecx,1また、を呼び出す前に、長さを 2 で割る (つまり ) 必要があります。これはWriteConsoleW、 の 3 番目の引数がWriteConsoleW書き込む文字数 (バイト数ではない) であるためです。


cldの先頭に命令を追加して、アドレスが正しい方向に移動GetFullPathすることを確認することもお勧めします。lodsw

于 2013-07-15T16:12:31.637 に答える