flat assembler
Message board for the users of flat assembler.

Index > Windows > Read command line arguments

Author
Thread Post new topic Reply to topic
patchariadog



Joined: 24 Mar 2013
Posts: 94
patchariadog 16 Nov 2013, 14:30
I am new to programming console programs in FASM. I just searched the internet for 1 hour and tried some stuff out but nothing seemed to work. My question is how do you read command line arguments and print them to the screen.

I need to figure this out because I am building and updater to one of my c++ programs in assembly. The c++ program is going to use shellexecute to send the file name of the c++ program to the assembly program so it know what file to update, so I really just need to be able to read one command line argument. this is what I have tried so far

Code:
format PE console 4.0

entry start

include 'C:\Users\Administrator\Programs\assembly\Fasm\INCLUDE\win32ax.inc'

section '.text' code readable executable

        start:

        push dword [esp + 4] ;argc is located at esp+4
        push fmt1
        ccall printf
        add esp, 8

        mov eax, dword [esp+8]  ;pointer to argv[0] is located at esp+8
        push dword [eax]                ;argv[0] pointer
        push fmt2
        ccall printf
        add esp, 8
        
        mov eax, dword [esp+8] ;pointer to argv[0]
        mov edx, dword [eax]    ;argv[0]
        push dword [edx]                ;argv[0][0] or [edx+1] for next character
        push fmt3
        ccall printf
        add esp, 8
        
        mov eax, dword [esp+8]  ;pointer to argv[0]
        push dword [eax+4]              ;move to next pointer / argv[1]
        push fmt4
        ccall printf
        add esp, 8
        
        mov eax, 0

        invoke  ExitProcess, 0

section '.data' data readable writeable

fmt1 db 'argc = %d', 10, 0
fmt2 db 'argv[0] =  %s', 10, 0
fmt3 db 'argv[0][0] = %c', 10, 0
fmt4 db 'argv[1] = %s', 10, 0

section '.idata' import data readable

        library kernel32, 'kernel32.dll',\
                msvcrt, 'msvcrt.dll'

        import  kernel32,\
                ExitProcess, 'ExitProcess'

        import  msvcrt,\
                printf, 'printf'
    


when I run it, it just says the file has stopped working and it does not print anything to the screen

thanks
Post 16 Nov 2013, 14:30
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20513
Location: In your JS exploiting you and your system
revolution 16 Nov 2013, 22:17
You can use the "GetCommandLine" function to read the line
Code:
invoke GetCommandLine    
Post 16 Nov 2013, 22:17
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1692
Location: Toronto, Canada
AsmGuru62 17 Nov 2013, 15:19
When FASM program starts -- it is just an entry point.
There are no argc or argv[] on stack, so you cannot use [esp + <ofs>].

You need to do the following:

1. Call GetCommandLineA()/GetCommandLineW() -- it will return a pointer to a string
2. Make a copy of the returned string
3. Parse the copy of the string using these rules:

- the parameters are separated by blanks with the following exception:
- if you encounter a double quote -- scan until the closing quote (ignoring the blanks)
Post 17 Nov 2013, 15:19
View user's profile Send private message Send e-mail Reply with quote
patchariadog



Joined: 24 Mar 2013
Posts: 94
patchariadog 20 Nov 2013, 03:51
thanks revolution and AsmGuru62

I used a combination of both of your ideas and now it works.

for anyone who needs the source code here it is

Code:

macro getstringlengthx86 string {

;works with dd and rb

mov edi,string
xor al,al
mov ecx,4294967295
repne scasb
mov eax,4294967294
sub eax,ecx
mov ecx,eax

}             

invoke GetCommandLineA
invoke lstrcpyA,commandlinearguments,eax
invoke GetModuleFileNameA,NULL,filename,280

getstringlengthx86 filename
mov esi,ecx
add esi,3


stdcall reverseastringx86,commandlinearguments,buffer1

;get the string length

mov edi,commandlinearguments
xor al,al
mov ecx,4294967295
repne scasb
mov eax,4294967294
sub eax,ecx
mov ecx,eax

sub ecx,esi
mov esi,commandlinearguments
mov edi,commandlinearguments2
rep movsb

stdcall reverseastringx86,commandlinearguments2,buffer1

;now the command line arguments without the filename are in the variable commandlinearguments2

proc reverseastringx86 uses ebx ecx esi,szString,szBuffer
;works with rb
        mov     esi,[szString]

        ;get string length
        mov edi,[szString]
        xor al,al
        mov ecx,4294967295
        repne scasb
        mov eax,4294967294
        sub eax,ecx
        lea ecx,[eax+1]

        mov     ebx,[szBuffer]
        mov     byte[ebx+ecx-1],0
        dec     ecx
  @@:
        lodsb
        mov     byte[ebx+ecx-1],al
        loop    @b
        rep movsb

        ;copy the buffer to the string

        mov esi,[szBuffer]
        mov edi,[szString]
        push edi
        mov edi,[szBuffer]
        xor al,al
        mov ecx,4294967295
        repne scasb
        mov eax,4294967294
        sub eax,ecx
        mov ecx,eax
        pop edi
        rep movsb

;clear the buffer

mov [szBuffer],0

        ret
endp  

section '.data' data readable writeable  

commandlinearguments rb 280
commandlinearguments2 rb 280
buffer1 rb 280
length rb 9
filename rb 280

    
Post 20 Nov 2013, 03:51
View user's profile Send private message Reply with quote
RIxRIpt



Joined: 18 Apr 2013
Posts: 50
RIxRIpt 20 Nov 2013, 05:59
If you are not against using wide chars, you can also try CommandLineToArgvW.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
Post 20 Nov 2013, 05:59
View user's profile Send private message Visit poster's website Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 24 Nov 2013, 01:04
Here is another way:
Code:
format PE CONSOLE
entry MAIN

include 'win32a.inc'
include 'equates\msvcrt.inc'
include 'equates\kernel32.inc'
include 'equates\gdi32.inc'
include 'equates\user32.inc'
include 'equates\shell32.inc'

MAX_FONTS = 40

section '.data' data readable writeable
  argvs       db "argv = %s",10,13,0
  argcs       db "argc = %d",10,13,0
  press_a_key db 10,13,"Press [SPACE] or [ESC] to exit",10,13,0

section '.code' code readable executable

proc MAIN
     local _Argv:DWORD, _Env:DWORD, _Argc:DWORD, StartInfo:STARTUPINFOA

     call    ChangeConsoleFont

     lea     eax, [_Argc]
     lea     ebx, [_Argv]
     lea     ecx, [_Env]
     lea     edx, [StartInfo]
     cinvoke __getmainargs, eax, ebx, ecx, 0, edx

     cinvoke printf, <"ARGC    = %d",13,10>, [_Argc]

     mov     eax, [_Argv]
     cinvoke printf, <"ARGV[0] = %s",13,10>, dword [eax]

     mov     eax, [_Env]
     cinvoke printf, <"ENV[0]  = %s",13,10>, dword [eax]

     call    WaitKey

     invoke  ExitProcess, 0
     return
endp

proc WaitKey
     cinvoke puts, press_a_key

     .repeat
             invoke  Sleep, 10
             invoke  GetAsyncKeyState, VK_ESCAPE
             and     eax, $8000
             jne     program_done
             invoke  GetAsyncKeyState, VK_SPACE
             and     eax, $8000
             jne     program_done
     .until  eax <> NULL

  program_done:
     return
endp

proc ChangeConsoleFont
     local hout:DWORD, numfonts:DWORD, count:DWORD

     invoke  GetStdHandle, STD_OUTPUT_HANDLE
     mov     [hout], eax

     invoke  GetNumberOfConsoleFonts
     mov     [numfonts], eax

     mov     [count], 0
     .repeat
             invoke  GetConsoleFontSize, [hout], [count]
             movsx   ecx, ax
             shr     eax, 16
             movsx   edx, ax
             .if     ecx = 10 & edx = 18
                     invoke  SetConsoleFont, [hout], [count]
                     return
             .endif
             mov     eax, [numfonts]
             inc     [count]
     .until  [count] = eax

     return
endp

section '.idata' import data readable writeable

  library msvcrt,'MSVCRT.DLL',\
          kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL',\
          gdi32,'GDI32.DLL',\
          shell32,'SHELL32.DLL'

  include 'apia\msvcrt.inc'
  include 'apia\kernel32.inc'
  include 'apia\user32.inc'
  include 'apia\gdi32.inc'
  include 'apia\shell32.inc'     
Post 24 Nov 2013, 01:04
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.