Чтобы узнать какие прописаны значения в командной строке нужно воспользоватся тандемом функций Код (ASM): call GetCommandLineW push offset pTemp push eax call CommandLineToArgvW После отработки в переменной - pTemp будет прописано количество параметров а на выходе в регистре - eax будет указатель на созданный список параметров который является массивом строк в формате - UNICODE В некоторых случаях мягко говоря это не совсем удобно Раньше я не сталкивался с командной строкой по причине ненадобности и вот теперь когда мне понадобилось обработать командную строку я мягко говоря был крайне удивлён что не существует функции для обработки параметров командной строки в формате - ASCII По этой причине я написал пользовательскую функцию - CommandLine$ и завернул её в макропроцедуру и если кому интересно можно ознакомится с этой реализацией Макрос имеет незатейлевое название с префиксом - @CommandLine Код (ASM): @CommandLine MACRO p1:= <32> local adr .data? adr byte p1 dup(?) .code push offset adr call CommandLine$ ENDM У макроса только один параметр и в нём по умолчанию прописано - 32 то есть если макрос объявить без параметра то в сегменте - .data? пропишется буфер размером 32 байта под четырёх-байтные данные если мысленно применить байтное смещение в буфере то это будет выглядеть так: [0-3] числовое значение (количество параметров) [4-7] адрес первого параметра (как правило имя или путь экзешника) [8-11] адрес второго параметра [12-15] адрес третьего параметра ну и так далее по интуитивно понятной логике в 32 байтном буфере по умолчанию уместится 7 адресов параметров с нулевым байтом в конце плюс первоначальный параметр (число этих параметров) Если вам потребуется больше или меньше параметров то размер буфера нужно увеличивать или уменьшать кратно четырём байтам но тогда макрос придётся прописывать с параметром если например нужно больше то так - @CommandLine 40 в этом случае в буфере можно поместить адреса 9 параметров а если например нужно меньше то так - @CommandLine 12 в этом случае в буфере можно поместить адреса только 2 параметров но я думаю 32 байтный буфер по умолчанию где макрос можно прописывать просто без параметра - @CommandLine это выше крыши хотя конечно кому как Пользовательская функция: Код (ASM): CommandLine$ proc uses esi edi pBuf:dword ;---------------------------------------- f GetCommandLine xchg esi,eax mov edi,pBuf push edi xor ecx,ecx xor edx,edx @@: mov al,byte ptr [esi] ;------------------------ .if al == 0 jmp @f .endif ;------------------------ .if al == 20h mov byte ptr [esi],0 xor ecx,ecx ;------------------------ .else ;---------------- .if ecx == 0 inc edx inc ecx add edi,4 mov dword ptr [edi],esi .endif ;---------------- .endif ;------------------------ inc esi jmp @b @@: pop eax mov dword ptr [eax],edx ;---------------------------------------- ret CommandLine$ endp На выходе в регистре - eax будет адрес созданного буфера Проверить работоспособность можно этой конструкцией Код (ASM): @CommandLine mov ecx,dword ptr [eax] .while ecx add eax,4 mov edx,dword ptr [eax] ;--------------- push eax push ecx invoke MessageBoxA,0,edx,0,32 pop ecx pop eax ;--------------- dec ecx .endw Проверять лучше бат-файлом создать бат-файл и положить его рядом с вашим экзешником в бат-файле прописать например вот так: Код (ASM): testing.exe Parametr_1 Parametr_2 Parametr_3 имя экзешника я применил - testing у вас оно может быть любое другое
В функции - CommandLine$ первой строчкой прописано - f GetCommandLine нужно вместо этого прописать - call GetCommandLine сам я вместо макроса - invoke пользуюсь своим макросом - f по этому забыл подправить чтобы вам было понятно Ещё раз прошу прощения
assch, Если уж пишешь код с намеком на библиотечность, то лучше сразу что-нибудь типа getopt запилить. Полезней же, чем просто макросами функционал апи дублировать.
rmn, я просто предложил определённую схему для работы с командной строкой но с большим бы интересом посмотрел ваше видение подобной реализации как говориться век живи век учись
В пользовательской функции я не учёл применения в параметрах апострофов а так как функция пробелы интерпретирует как разделители параметров то при применении апострофов это не приемлемо Для этого поставил фильтр который будет работать тривиально в лоб при захвате одного из апострофов (" - 22h) или (' - 27h) фильтр дождётся пока открывающий апостроф не закроется при работе фильтра пробелы будут игнорироватся например если в бат-файле прописать Код (ASM): testing.exe Parametr_1 "C:\Program Files\Windows Media Player\wmplayer.exe" Parametr_3 функция разложит командную строку на четыре параметра 1 - testing.exe 2 - Parametr_1 3 - C:\Program Files\Windows Media Player\wmplayer.exe 4 - Parametr_3 В логике функции - CommandLineToArgvW не много более расширенная интерпретация работы с двойным апострофом да да именно с двойным потому что одиночный апостроф она игнорирует в чистом виде как это делает - CommandLineToArgvW в моей пользовательской функции сделать это не возможно потому что это совершенно два разных подхода библиотечная функция - CommandLineToArgvW помимо буфера командной строки динамически выделяет свой буфер под прописанные параметры и этот буфер програмист должен потом по правилам хорошего тона закрыть а моя функция работает только с буфером командной строки в котором вместо разделяемых пробелов прописывает нули попутно заполняя сегментный буфер соответствующими адресами взятыми из буфера командной строки Я думаю простого фильтра для апострофов который работает в лоб для большинства случаев будет вполне премлемо кстати говоря этот фильтр прекрасно работает с любым из апострофов а вот функция - CommandLineToArgvW почему то не хочет работать с одиночным апострофом корректно обрабатывая только двойной апостроф Исправленная пользовательская функция с фильтром для апострофов Код (ASM): CommandLine$ proc uses esi edi pBuf:dword ;---------------------------------------- call GetCommandLine xchg esi,eax mov edi,pBuf push edi xor ecx,ecx xor edx,edx @@: mov al,byte ptr [esi] ;------------------------ .if al == 0 jmp @f .endif ;------------------------ .if al == 22h || al == 27h mov cl,al mov byte ptr [esi],0 inc esi add edi,4 mov dword ptr [edi],esi inc edx loc_1: mov al,byte ptr [esi] ;------------ .if al == 0 jmp @f .endif ;------------ .if al == cl mov byte ptr [esi],0 xor ecx,ecx inc esi jmp @b .endif ;------------ inc esi jmp loc_1 .endif ;------------------------ .if al == 20h mov byte ptr [esi],0 xor ecx,ecx ;------------------------ .else ;---------------- .if ecx == 0 inc edx inc ecx add edi,4 mov dword ptr [edi],esi .endif ;---------------- .endif ;------------------------ inc esi jmp @b @@: pop eax mov dword ptr [eax],edx ;---------------------------------------- ret CommandLine$ endp Можно конечно сделать обработку командной строки используя функцию - CommandLineToArgvW и потом своим алгоритмом или функцией - WideCharToMultiByte добиться желаемого результата но для этого как минимум понадобится подключить библиотеку - Shell32.dll и дополнительный динамический или сегментный буфер По большому счёту эту реализацию работы с командной строкой можно расматривать как альтернативный инструмент который в свою очередь можно легко и просто корректировать прописывая изменения в пользовательскую функцию Я наверное не ошибусь если предположу что у любого программиста таких (пользовательских инструментов) вагон и маленькая тележка