Командная строка. Решение в лоб не проходит

Тема в разделе "WASM.BEGINNERS", создана пользователем mutex_llc, 1 дек 2008.

  1. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Простым способом проверяю имеется ли пробел (т.е.аргумент) в командной строке. Результат всегда положителен: все время получаю сообщение, что аргумент есть. Т.е. отрицательная ветвь кода не получает управление несмотря на то, что запускаю программу из Проводника, следовательно без аргументов. Так же, когда запускаю через Тотал Коммандер. Версия ОС - XP SP3.
    Фрагмент кода:

    invoke GetCommandLine
    mov dCmd,eax
    invoke lstrlen,eax
    mov ecx,eax
    cmp ecx,0
    je netu ;нет аргумента
    mov esi,dCmd
    sravn:
    cmp byte ptr [esi],0
    je netu
    cmp byte ptr [esi],20h
    je est ;аргумент есть
    inc esi
    loop sravn

    В чем дело? Какая-то тонкость в механизме ОС? Как решать проблему?
    Еще: антивирус Доктор Веб считает трояном эту крохотную программку. Почему?

    Приложение: Build.bat, ChkCmdArg.asm

    PS. Забыл сказать: под отладчиком Олли программа работает нормально. Если задать параметры в ком.строке, выполняется отрицательная ветвь.
     
  2. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Аргумент есть всегда: им является полный путь к экзешнику.
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    SII
    Не всегда. Мне ничто не помешает запустить процесс так, чтобы GetCommandLine возвращала указатель на пустую строку.
     
  4. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    l_inc
    Не знаю, как при запуске через задницу :) Но при обычном запуске всегда будет полная спецификация исполняемого файла, поэтому и длина командной строки будет больше нуля.

    Пы.Сы. А как запустить, чтобы с пустой комстрокой? А то интересно... :)
     
  5. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Под отладчиком нормально вижу этот путь. Я имел ввиду собственный аргумент запускаемой программы.

    Пошаговое исполнение под отладчиком показывает, что все верно, в т.ч. под Ida Pro. А отдельное самостоятельное выполнение под непосредственно Windows неверно. Что же происходит-то?
    Линкование делалось под /SUBSYSTEM:WINDOWS, компиляция по MASM 6.14.8444.

    Может программа слишком коротка и запуск программы операционной системой XP/SP3 имеет какую-то тайну для "коротышек"?
     
  6. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    не вникал глубоко, но обращаю внимание, что аргумент, в т.ч. первый - имя запускаемого файла, может быть в кавычках и содержать пробелы, а также если командная строка завершается одним или более пробелами, после которых ничего нет, то ваш код все равно воспримет это как наличие аргумента.

    вот мой код на фасме:
    Код (Text):
    1. ;=======================================================================
    2. proc GetParameter pString ; v.1.0
    3. ;-----------------------------------------------------------------------
    4. ;   searches for the beginning of the parameter in string,
    5. ;   skipping leading tabs and spaces, then searches for the end
    6. ;   of this parameter, terminated with zero, space or tab.
    7. ;   returns pointer to start of parameter in eax,
    8. ;   pointer to first byte after parameter in edx,
    9. ;   and length of parameter in ecx.
    10. ;   spaces and tabs inside quotes not processed as dividers.
    11. ;   if there is no parameters eax will be equal to edx and point to
    12. ;   termination zero, ecx will be zero, ZF will be on.
    13. ;   passed string will not be changed.
    14. ;-----------------------------------------------------------------------
    15.     push esi
    16.     mov esi,[pString]
    17. ;-----------------------------------------------------------------------
    18. .search_start:
    19.     mov edx,esi
    20.     lodsb
    21.     cmp al,20h
    22.     je  .search_start
    23.     cmp al,9
    24.     je  .search_start
    25.     or  al,al
    26.     jz  .done
    27. ;-----------------------------------------------------------------------
    28.     mov ah,20h
    29.     mov ch,'"'
    30.     jmp @F
    31. .search_loop:
    32.     lodsb
    33. @@:
    34.     or  al,al
    35.     jz  .done
    36.     cmp al,9
    37.     jne .not_tab
    38.     mov al,20h
    39. .not_tab:    
    40.     cmp al,ah
    41.     je  .found
    42.     cmp al,ch
    43.     jne .search_loop
    44.     mov ah,ch          
    45.     jmp .search_loop
    46. .found:
    47.     cmp ah,ch
    48.     mov ah,20h
    49.     je  .search_loop    
    50. ;-----------------------------------------------------------------------
    51. .done:
    52.     dec esi
    53.     mov eax,edx
    54.     mov ecx,esi
    55.     mov edx,esi
    56.     sub ecx,eax
    57.     pop esi
    58.     ret  
    59. ;-----------------------------------------------------------------------
    60. endp
    61. ;=======================================================================
    - эта процедура ищет в строке параметр, оптимизирована под вызов из ассемблера ;)

    через CreateProcess, однако, если все-таки нужно передать параметры, то первым все-равно нужно указать имя ехе-шника, иначе программа ступит (она же не знает, каким образом ее запускали, поэтому первый параметр воспримет как свое имя)
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    SII
    Так это не через задницу. В CreateProcess просто указать "" в параметре lpCommandLine, а не NULL. Если NULL, то система, разумеется, подставит путь в качестве параметра.
    shoo
    Это скорее рекомендация, чем закон. Для сторонних программ, не содержащих багов в обработке командной строки, достаточно начать командную строку с пробела (всё, что до него, особого значения не имеет, даже если до этого пробела ничего нет). А для своих... ну это уже дело хозяйское, как обрабатывать собственную командную строку: там уже что угодно писать можно.
     
  8. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Пробел может встретиться в именах файлов. Наврное, нельзя считать пробел разделителем между параметрами коммандной строки.
     
  9. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    AsmGuru62
    для этого-то и придумали заключать такие пути/имена в кавычки, и нормальная прога должна понимать, что пробел между кавычек это ещё не разделитель ;) а так проверь - любая прога требующая командную строку заглючит если получит путь с пробелами без кавычек :)
     
  10. djmans

    djmans New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2006
    Сообщения:
    312
    Сушествует прекрасная апи CommandLineToArgvW, она прекрасно все парсит.
     
  11. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Уважаемые коллеги.

    Речь я веду только о запуске программы штатными средствами операционной системы. Насколько я в курсе если имя файла содержит пробел, то оно автоматически целиком заключается в кавычки для передачи в качестве параметра командной строки. Обнаружив такой пробел мы можем считать, что по крайней мере мы имеем один аргумент.

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

    Какие есть мнения на этот счёт?

    Shoo спасибо за код. Разбираю, к сожалению ФАСМом не знаком.
    Djmans, этот АПИ имеет ANSI-версию CommandLineToArgvA?
     
  12. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Код (Text):
    1. .data
    2. cmd_args dd 0
    3. .CODE
    4. start:
    5. invoke GetCommandLine
    6. invoke PathGetArgs,eax
    7. mov cmd_args,eax
    8. mov al,[eax]
    9. ;Если параметры заключены в кавычки - убрать кавычки!
    10. .IF al != 0
    11.     .IF al == '"'
    12.         invoke PathUnquoteSpaces,cmd_args
    13.         mov cmd_args,eax
    14.     .ENDIF
    15. .ENDIF
    16. xor ecx,ecx
    17.    invoke MessageBox,ecx,cmd_args,ecx,ecx
    18.    invoke ExitProcess,0
    19. end start
     
  13. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    mutex_llc
    код ищет начало аргумента, отбрасывая ведущие пробелы и табы (на всякий случай), если оно найдено и это кавычка - ищет вторую кавычку, если нет - ищет следующий пробел или таб.

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

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Asterix
    где-то я эти еретические макросы уже видел :)
     
  15. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Shoo, спасибо, но не могу и не хочу проверить код, который делает парсинг. В парсинге не нуждаюсь.

    Мой код элементарно прост, но не работает. Не смогли бы, коллеги, скачать и проверить эту примитивщину. Работает код у вас или нет?
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    mutex_llc
    Вы издеваетесь?
    Примерно диалог выглядит так:
    mutex_llc: Сколько будет 2+2?
    all: 4
    mutex_llc: Я не прошу назвать мне ответ, я прошу сказать, сколько будет 2+2.

    Теперь по сути:
    Вы издеваетесь? :) Сами же написали:
    Ну так и где у Вас в коде учитывается, что путь к файлу, заключённый в кавычки, может иметь пробел, но дополнительных аргументов при этом нет?
    Правильно было бы сказать: "Мой код элементарно прост, поэтому не работает". Не учитывается наличие пробелов в пути к файлу.
     
  17. djmans

    djmans New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2006
    Сообщения:
    312
    CommandLineToArgvA к сожелению не сущетвует.
     
  18. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    > CommandLineToArgvA к сожелению не сущетвует.
    Чего я и боялася :)

    > Вы издеваетесь?
    Не, боже упаси. Как могли подумать такое? Запутался я, уже грешу на ОС, что она криво стоит и т.д.

    > Правильно было бы сказать: "Мой код элементарно прост, поэтому не работает". Не учитывается наличие пробелов в пути к файлу.
    Не понял! Элементарный код всегда надежнее, чем сложный, закрученный и запутанный. Не надо умножать сущности сверх необходимого. Лезвие Оккама.
     
  19. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    mutex_llc
    Против лезвия Оккама ничего не имею. Но у многих проблематично с тем, чтобы определить, где находится граница необходимого. И Вы в данном случае до неё не дотянули.
    Точно. Это ж просто ужас, как страшно, вызвать на одну API-функцию (WideCharToMultiByte) больше. Лезвие Оккама нам этого не простит.
     
  20. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    I-inc, это уже оффтоп. Да с неадекватными бесполезно спорить и что-то доказывать. Как говорится, учите матчасть прежде чем пререкаться по пустому поводу. Я больше не отвечаю Вам.