0

我已经用这个问题折磨自己一个月了,我要放弃了。这是一个简单的程序,我只是不明白为什么不能正常工作。所以,我要创建的是一个简单的应用程序,它将解析命令行并显示第一个参数,这是可执行文件的完整路径。这就是我的代码的样子:

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], esijmp应该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在调用 之前,您还需要将长度除以二(即) WriteConsoleW,因为 to 的第三个参数WriteConsoleW是要写入的字符数(不是字节数)。


cld在开头添加一条指令以GetFullPath确保lodsw将地址移动到正确的方向也是一个好主意。

于 2013-07-15T16:12:31.637 回答