NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: alexbnc on July 29, 2013, 06:02:26 PM
-
I've been torturing myself with this issue for a month and I'm about to give up. It is a simple program and I just can't see why is not working properly.
So, what I am trying to do create is a simple application that will parse the command line and display the first argument, which is the full path to the executable.
This is how my code looks like:
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, e
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
ret 8
CloseApp:
push ebx
call ExitProcess
pop ebx
ret
Well, I might have misspelled or missed something but that is not the problem. The code is compiled and built successfully but the message that I see is only the name of the executable, not the full path that I expect. If the full path is "D:\My Projects\NASM\Demo.exe" I only see "Demo". If before calling ShowText I prepare the arguments for the message variable it works and I can see the text correctly, so I think the problem lies in getting the pointer and length of the full path correctly. Yet, when studying the running of the application with OllyDbg I can see that correct values are stored in the BSS section. This is very weird and maybe somebody with a better eye can catch the cause of it. Thanks in advance
-
To make life easier, you could use CommandLineToArgvW which will return the count of args. To simplify, I used printf:
%define STD_OUTPUT_HANDLE -11
; Shell32.dll
extern CommandLineToArgvW
; Kernel32.dll
extern ExitProcess, WriteConsoleW, LocalFree
extern GetStdHandle, GetCommandLineW
%define GetCommandLine GetCommandLineW
; msvcrt.dll
extern _printf
section .bss
stdout resd 1
szArglist resd 1
nArgs resd 1
section .data
fmtst db "%ws", 13, 10, 0
section .text
global start
start:
push STD_OUTPUT_HANDLE
call GetStdHandle
mov dword [stdout], eax
call GetCommandLine
push nArgs
push eax
call CommandLineToArgvW
mov dword [szArglist], eax
mov esi, eax
xor ebx, ebx
sub dword [nArgs], 1
.DisplayArgs:
push dword [esi + 4 * ebx]
push fmtst
call _printf
add esp, 4 * 2
inc ebx
cmp ebx, dword [nArgs]
jle .DisplayArgs
push dword [szArglist]
call LocalFree
push 0
call ExitProcess
-
Thanks for that solution. It is a good alternative yet I would really like to understand what is the problem in my case. It is frustrating to see that something that is supposed to work just doesn't. Computers don't do things at random and without explanation. Today I tried this
...
GetCommandLine:
cld
call GetCommandLineW ; UNICODE
mov esi, eax
; display it here
push dword eax
push dword 128
call ShowText
...
I am trying to get the entire, or at least the first 128 characters of the full command line. I still get weird characters, so I am really really lost right now. So, if I have my executable in "D:\Project\My Demo\Test.exe", I add this to Path and I execute "Test --firstarg" in the cmd what I get is
Test --firstarg Test --firstarg Winsta0\Default =::=:: \=C:=C:\Users\Alex =D:=D:\Project\MyDemo\ ALLUSERSPROFILE