从程序集中的命令行获取完整路径

时间:2013-07-15 14:38:23

标签: assembly unicode command-line path nasm

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

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”我只看到“演示”。如果在调用ShowText之前我准备了message变量的参数它可以工作,我可以正确地看到文本,所以我认为问题在于正确获取完整路径的指针和长度。然而,在研究使用 OllyDbg 运行应用程序时,我可以看到正确的值存储在BSS部分中。这是非常奇怪的,也许有一个更好的眼睛的人可以找到它的原因。提前致谢

更新 今天我试着像这样显示整个命令行:

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

我仍然看到奇怪的角色。我知道有其他选择,但我只是想知道为什么第一眼看上去那么简单的东西不起作用。我的意思是,计算机不会随意做任何事情而且没有解释。

1 个答案:

答案 0 :(得分: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之后,您应该jmpShowPath。否则,你最终会检查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),因为WriteConsoleW的第三个参数是要写入的字符数(不是字节数)


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