Assembly 从程序集中的命令行获取完整路径
我已经为这个问题折磨了自己一个月了,我打算放弃。这是一个简单的程序,我就是不明白为什么不能正常工作。 因此,我试图创建一个简单的应用程序,它将解析命令行并显示第一个参数,这是可执行文件的完整路径。 我的代码是这样的:Assembly 从程序集中的命令行获取完整路径,assembly,unicode,command-line,path,nasm,Assembly,Unicode,Command Line,Path,Nasm,我已经为这个问题折磨了自己一个月了,我打算放弃。这是一个简单的程序,我就是不明白为什么不能正常工作。 因此,我试图创建一个简单的应用程序,它将解析命令行并显示第一个参数,这是可执行文件的完整路径。 我的代码是这样的: use32 [EXTERN GetStdHandle] [EXTERN GetCommandLineW] [EXTERN WriteConsoleW] [EXTERN ExitProcess] [section .bss] StdHandle resd 1 PathStart
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
我仍然看到奇怪的角色。我知道还有其他选择,但我只是想知道为什么这么简单的事情在第一眼就不起作用。我的意思是,计算机做事情不是随意的,没有解释的
jne解析;否则,继续解析
mov-dword[PathStart],ecx;保存路径字符串的开头
mov-dword[PathEnd],esi;保存路径字符串的结尾
继续讨论:
cmp-ax,0;如果这不是命令行的结尾
jne解析;返回分析
在
mov dword[PathEnd]之后,esi
您应该jmp
到ShowPath
。否则,您将检查ax==0——由于它包含一个空格字符,因此显然不会是这样——并且您将返回到解析
mov-ecx,[PathStart];将路径字符串的开头保存在ECX中
mov-ebx[PathEnd];在EBX中保存路径字符串的结尾
子ecx、ebx;计算ECX中路径字符串的大小
您正在从
PathStart
中减去PathEnd
。应该是相反的。在调用WriteConsoleW
之前,还需要将长度除以2(即shr ecx,1
),因为WriteConsoleW
的第三个参数是要写入的字符数(而不是字节数)
在
GetFullPath
的开头添加cld
指令也可能是一个好主意,以确保lodsw
将地址移动到正确的方向。什么的完整路径?您能给出一个示例命令行和预期的输出吗?该命令行包含可执行文件的路径以及用户指定的其他参数。示例:“C:\Program Files\MyApp\AppExe.exe”“arg1”“arg2”。在这里,我只想显示第一部分(可执行文件的完整路径),即“C:\Program Files\MyApp\AppExe.exe”。您正在测试的路径包含一个空格(在我的和项目之间)。您的解析代码无法正确处理此类情况。您可能需要研究调用。这将为您完成解析,正确处理引用参数中的空格、转义字符等。我可以使用它作为最后一个选项,但看到如此简单的东西不起作用,令人沮丧。即使它会在第一个空格处停止,至少在那之前我应该看到文本。奇怪的是,它仍然不起作用。仅显示“MyApp”。错误的开始,错误的长度这对我来说很有效(我使用masm32来确认我建议的更改给出了期望的结果)。