简体   繁体   English

MASM32 x86 windows程序集GetCommandLineToArgvW

[英]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: 例如:

  • D:\\masm32>Hello.exe I am Hello D:\\ masm32> Hello.exe我是你好
  • 4 4
  • D:\\masm32> d:\\ MASM32>

CommandLineToArgvW has at least three quirks you have to watch out for: CommandLineToArgvW至少有三个怪癖需要注意:

  1. 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

  2. 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”。

  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM