[英]MASM32 x86 windows assembly GetCommandLineToArgvW
I would like to ask how to use the CommandLineToArgvW function in x86 assembly. 我想问一下如何在x86程序集中使用CommandLineToArgvW函数。 I'm having trouble with it.
我遇到了麻烦。 All I can print as of today is the number of the arguments along with the program execution in cmd.
我今天打印的所有内容都是参数的数量以及cmd中的程序执行。 I would like to save the arguments in different variables.
我想将参数保存在不同的变量中。 How can I do it?
我该怎么做?
My code looks like this: 我的代码看起来像这样:
include \masm32\include\masm32rt.inc
.data
Format db "%d", 10, 0
.data?
Arguments db 100 dup(?)
.code
start:
mov esi, offset Arguments
push ebp
mov ebp, esp
sub esp, 4
call GetCommandLineW
lea ecx, dword ptr[ebp - 4]
push ecx
push eax
call CommandLineToArgvW
mov esi, eax
push offset Arguments
call StdOut
push dword ptr [ebp - 4]
push offset Format
call crt_printf
add esp, 8
push 0
call ExitProcess
end start
My output as of now is the number of arguments. 我现在的输出是参数的数量。 For example:
例如:
CommandLineToArgvW
has at least three quirks you have to watch out for: CommandLineToArgvW
至少有三个怪癖需要注意:
The result is an array of pointers to wide -character strings. 结果是一个指向宽字符串的指针数组。
The MASM32 function crt_printf
uses the function printf
from the Microsoft VC runtime library (msvcrt.dll). MASM32函数
crt_printf
使用Microsoft VC运行时库(msvcrt.dll)中的函数printf
。 Therefore, you can use an uppercase 'S' as the type field character. 因此,您可以使用大写的“S”作为类型字段字符。 Take a look at
printf
Type Field Characters on MSDN . 看一下MSDN上的
printf
Type Field Characters 。
The result is the address of the first element of an array of pointers to a string. 结果是指向字符串的指针数组的第一个元素的地址。
Most print functions expect a pointer to a string, not a pointer to a pointer to a string. 大多数打印函数都需要指向字符串的指针,而不是指向字符串指针的指针。 You have to dereference that address to get a pointer to the string.
您必须取消引用该地址才能获得指向该字符串的指针。 A command line "Hello.exe I am Hello" will be splitted into four strings: "Hello.exe", "I", "am", "Hello".
命令行“Hello.exe I is Hello”将被分为四个字符串:“Hello.exe”,“I”,“am”,“Hello”。 The pointers to these strings are to find in an array with 4 pointers: [pointer to "Hello.exe"], [pointer to "I"], and so on.
指向这些字符串的指针是在一个包含4个指针的数组中找到:[指向“Hello.exe”的指针],[指向“I”的指针],依此类推。 Assume the function
CommandLineToArgvW
has a return value EAX=0x001445A8. 假设函数
CommandLineToArgvW
具有返回值EAX = 0x001445A8。 The Hexdump looks like Hexdump看起来像
Address Hex dump ASCII 001445A8 B8 45 14 00|CC 45 14 00|D0 45 14 00|D6 45 14 00| ¸E.ÌE.ÐE.ÖE. 001445B8 48 00 65 00|6C 00 6C 00|6F 00 2E 00|65 00 78 00| Hello..ex 001445C8 65 00 00 00|49 00 00 00|61 00 6D 00|00 00 48 00| e...I...am..H. 001445D8 65 00 6C 00|6C 00 6F 00|00 00 00 00|00 00 00 00| ello........
At address 0x001445A8 is a pointer to 0x001445B8 (displayed in the dump in little endian format) and this is the beginning of "Hello.exe" in wide-character format. 地址0x001445A8是指向0x001445B8的指针(以小端格式转储显示),这是宽字符格式的“Hello.exe”的开头。 The next pointer is 4 bytes behind 0x001445A8: 0x001445CC - points to "I".
下一个指针是0x001445A8后面的4个字节:0x001445CC - 指向“I”。 The next pointer is 4 bytes away and so on.
下一个指针距离4个字节,依此类推。 You can quickly go through that array just by adding 4. And you can easily get the address of a string in the middle of the list by multiplying the index by 4 - the pointer to the third string ("am", index: 2) is at 0x001445A8 + 2 * 4 = 0x001445B0 => 0x001445D0 => "am".
您可以通过添加4来快速浏览该数组。您可以通过将索引乘以4轻松获取列表中间的字符串地址 - 指向第三个字符串的指针(“am”,index:2)位于0x001445A8 + 2 * 4 = 0x001445B0 => 0x001445D0 =>“am”。
The function allocates memory, which has to be manually freed with LocalFree
. 该函数分配内存,必须使用
LocalFree
手动释放。
I changed your program as little as possible: 我尽可能少地改变你的程序:
include \masm32\include\masm32rt.inc
.data
Format db "argc: %d", 10, 0
fmt db "%S",10,0 ; %S: printf wide-character string / wprintf single-character string
szArglist dd ?
.code
start:
push ebp
mov ebp, esp
sub esp, 4
; https://msdn.microsoft.com/library/windows/desktop/ms683156.aspx
call GetCommandLineW ; EAX = pointer to the command line
; https://msdn.microsoft.com/library/windows/desktop/bb776391.aspx
lea ecx, dword ptr[ebp - 4] ; Get the current address of [ebp-4]
push ecx ; int *pNumArgs (Pointer to a SDWORD, here at ebp-4)
push eax ; LPCWSTR lpCmdLine (from GetCommandLineW)
call CommandLineToArgvW
mov [szArglist], eax ; Store the result of CommandLineToArgvW (at least for LocalFree)
mov esi, eax ; ESI = address of a pointer (the first element in szArglist)
mov ebx, [ebp-4] ; Countdown the number of arguments
@@: ; Loop
push dword ptr [esi] ; Pointer to a string (dereferenced esi)
push OFFSET fmt ; Format string
call crt_printf ; printf (""%S\n", esi)
add esp, 8 ; Clear the stack after printf
add esi, 4 ; Next address of a pointer (next element of szArglist)
dec ebx ; Countdown the number of arguments
jne @B ; Loop to the last @@
push dword ptr [szArglist]
call LocalFree ; Free the memory occupied by CommandLineToArgvW
push dword ptr [ebp - 4] ; Value that is stored in [ebp-4]
push offset Format ; Pointer to format string
call crt_printf ; printf ("argc: %d\n", [ebp-4])
add esp, 8 ; Clear the stack after printf
push 0
call ExitProcess
end start
The MASM32 function StdOut
cannot handle wide-character-strings. MASM32函数
StdOut
无法处理宽字符串。 You have to convert them first to ANSI strings. 您必须先将它们转换为ANSI字符串。 The Windows function for that purpose is
WideCharToMultiByte
: 用于此目的的Windows功能是
WideCharToMultiByte
:
include \masm32\include\masm32rt.inc
.data
szArglist dd ?
buf db 1024 DUP (?)
crlf db 13, 10, 0 ; New line
.code
start:
push ebp
mov ebp, esp
sub esp, 4
; https://msdn.microsoft.com/library/windows/desktop/ms683156.aspx
call GetCommandLineW ; EAX = pointer to the command line
; https://msdn.microsoft.com/library/windows/desktop/bb776391.aspx
lea ecx, dword ptr[ebp - 4] ; Get the current address of [ebp-4]
push ecx ; int *pNumArgs (Pointer to a SDWORD, here at ebp-4)
push eax ; LPCWSTR lpCmdLine (from GetCommandLineW)
call CommandLineToArgvW
mov [szArglist], eax ; Store the result of CommandLineToArgvW (at least for LocalFree)
mov esi, eax ; ESI = address of a pointer (the first element in szArglist)
mov ebx, [ebp-4] ; Countdown the number of arguments
@@: ; Loop
; https://msdn.microsoft.com/library/windows/desktop/dd374130.aspx
push NULL ; LPBOOL lpUsedDefaultChar
push NULL ; LPCSTR lpDefaultChar
push SIZEOF buf ; int cbMultiByte
push OFFSET buf ; LPSTR lpMultiByteStr
push -1 ; int cchWideChar
push [esi] ; LPCWSTR lpWideCharStr (dereferenced esi)
push 0 ; DWORD dwFlags
push 0 ; UINT CodePage
call WideCharToMultiByte
push OFFSET buf ; Pointer to an ANSI string
call StdOut
push OFFSET crlf ; New line
call StdOut
add esi, 4 ; Next address of a pointer (next element of szArglist)
dec ebx ; Countdown the number of arguments
jne @B ; Loop to the last @@
push dword ptr [szArglist]
call LocalFree ; Free the memory occupied by CommandLineToArgvW
push OFFSET buf
push dword ptr [ebp - 4]
call dwtoa
push OFFSET buf ; Pointer to a string
call StdOut ; printf (""%S\n", esi)
push OFFSET crlf
call StdOut
push 0
call ExitProcess
end start
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.