2013-07-15 3 views
0

Я уже много месяцев пытаюсь проделать эту проблему, и я собираюсь сдаться. Это простая программа, и я просто не понимаю, почему она работает неправильно. Итак, я пытаюсь создать это простое приложение, которое будет анализировать командную строку и отображать первый аргумент, который является полным путем к исполняемому файлу. Это как мой код выглядит следующим образом:Получить полный путь из командной строки в сборке

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. Это очень странно, и, возможно, кто-то с лучшим глазом может понять причину этого. Заранее спасибо

UPDATE Сегодня я попытался отобразить всю командную строку:

GetCommandLine: 
     cld 
     call GetCommandLineW ; UNICODE 
     mov esi, eax 
     ; display it here 
     push dword  eax 
     push dword  128 
     call ShowText 

и я все еще вижу странные символы. Я знаю, что есть альтернативы, но я просто хочу знать, почему что-то настолько простое с первого взгляда не работает. Я имею в виду, что компьютеры не делают ничего наугад и без объяснений.

+0

Полный путь _what_? Не могли бы вы привести пример командной строки и ожидаемый результат? – Michael

+0

Командная строка содержит путь к исполняемому файлу и другие аргументы, которые пользователь указывает. Пример: «C: \ Program Files \ MyApp \ AppExe.exe» «arg1» «arg2». Отсюда я хочу отобразить только первую часть (полный путь к исполняемому файлу), которая представляет собой «C: \ Program Files \ MyApp \ AppExe.exe» – ali

+0

вопрос reedited – ali

ответ

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) до вызова WriteConsoleW, поскольку третий аргумент WriteConsoleW - это количество символов для записи (не количество байтов).


Он также может быть хорошей идеей, чтобы добавить cld инструкции в начале GetFullPath, чтобы убедиться, что lodsw перемещает адрес в правильном направлении.

+0

странно, что он все еще не работает. отображается только «MyApp». Неверный старт, неправильная длина – ali

+0

Это работает для меня (я использовал masm32, чтобы подтвердить, что мои предложенные изменения дали желаемый результат). – Michael

+0

вопрос повторно – ali

Смежные вопросы