我一直在用这个问题折磨自己一个月,我即将放弃。这是一个简单的程序,我只是看不出为什么不能正常工作。 所以,我要创建的是一个简单的应用程序,它将解析命令行并显示第一个参数,这是可执行文件的完整路径。 这就是我的代码的样子:
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
我仍然看到奇怪的角色。我知道有其他选择,但我只是想知道为什么第一眼看上去那么简单的东西不起作用。我的意思是,计算机不会随意做任何事情而且没有解释。
答案 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
之后,您应该jmp
到ShowPath
。否则,你最终会检查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
以正确的方向移动地址。