Simple console piping example

Started by Vortex, January 22, 2012, 11:25:39 AM

Previous topic - Next topic

Vortex

Here is a simple console pipe example. The executable pipe.exe reads data from STDIN and converts it to uppercase.

dir /b | pipe

BUILD.BAT
CRT0
FILES.TXT
PIPE.ASM
PIPE.EXE
PIPE.INC
SAMPLE.TXT
STDOUT.ASM
UPPERCASE.ASM


pipe "This is a test"

THIS IS A TEST


Source code :


include pipe.inc

BUFSIZE equ 1024

.data?

dwRead  dd ?
buffer  db BUFSIZE dup(?)

.code

main PROC C uses esi argc:DWORD,argv:DWORD

LOCAL hInput:DWORD

    invoke  GetStdHandle,STD_INPUT_HANDLE
    mov     hInput,eax

    mov     esi,OFFSET buffer
    cmp     argc,1+1
    jne     @f
    mov     edx,argv
    mov     esi,DWORD PTR [edx+4]
    call    PrintStr
    ret
@@:
    invoke  ReadFile,hInput,esi,BUFSIZE,ADDR dwRead,NULL
    test    eax,eax
    je      @f
    cmp     dwRead,0
    je      @f
    mov     eax,dwRead
    mov     BYTE PTR [esi+eax],0
    call    PrintStr
    jmp     @b
@@:
    ret

main ENDP

PrintStr PROC

    invoke  uppercase,esi
    invoke  StdOut,eax
    ret

PrintStr ENDP

END
Code it... That's all...


CLR

Where is @f, @b? Oh I miss the basics

TimoVJL

#3
From PellesC help:
Command line tools -> POASM macro assembler -> Introduction -> Special code labels:
QuoteSpecial code labels (IA32, AMD64)

The special label @@ can be used anywhere to create an anonymous label. This can be useful for short jumps, since you don't need to invent a new label name. For longer jumps, it's normally better to use a more descriptive name.

To jump to the nearest preceding anonymous label, use @B (back) as the jump instructions operand. To jump to the nearest following anonymous label, use @F (forward) as the operand. Since @B and @F always reference the nearest label, there is no problem having multiple anonymous labels in the same program.
May the source be with you


Vortex

Hi CLR,

Thanks for your kind words.

You can replace anonymous labels with regular ones :


_loop:
    invoke  ReadFile,hInput,esi,BUFSIZE,ADDR dwRead,NULL
    test    eax,eax
    je      finish
    cmp     dwRead,0
    je      finish
    mov     eax,dwRead
    mov     BYTE PTR [esi+eax],0
    call    PrintStr
    jmp     _loop
finish:
    ret
Code it... That's all...

CLR


Grincheux

#7
And I spent two days searching a similar code!

It is not in assembler but it does the same thing. ShellHelper is for executing a command or a batch file. It is not me who wrote it. It is a mixed of Microsoft (CreateProcess example) and others web sites and finally some ideas of mine. I made a generic function.

The first code is the ShellHelper function and following it ther is an example for calling. I wrote it for my editor that creates projects and launch the compiler. For the instant only the build command seems ok.


LPSTR ShellHelper(LPSTR __lpszCommand,LPSTR __lpszDirectory)
{
   alignas(HANDLE)   HANDLE   _hStdInPipeRead ;
   alignas(HANDLE)   HANDLE   _hStdInPipeWrite ;
   alignas(HANDLE)   HANDLE   _hStdOutPipeRead ;
   alignas(HANDLE)   HANDLE   _hStdOutPipeWrite ;

   alignas(HANDLE)   SECURITY_ATTRIBUTES   _Sa ;
   alignas(HANDLE)   STARTUPINFO         _Si;
   alignas(HANDLE)   PROCESS_INFORMATION   _Pi;

   alignas(HANDLE)   LPSTR   _lpszBuffer ;

   alignas(int)   BOOL   _bResult ;
   alignas(int)   char   _szComSpec[256] ;
   alignas(int)   char   _szCommand[1024] ;

   _bResult = FALSE ;
   _lpszBuffer = NULL ;

   _hStdInPipeRead = NULL ;
   _hStdInPipeWrite = NULL ;
   _hStdOutPipeRead = NULL ;
   _hStdOutPipeWrite = NULL ;

   MemorySetTo0(&_Si,sizeof(STARTUPINFO)) ;
   MemorySetTo0(&_Pi,sizeof(PROCESS_INFORMATION)) ;

   MemorySetTo0(_szCommand,sizeof(_szCommand)) ;
   MemorySetTo0(_szComSpec,sizeof(_szComSpec)) ;

   _Sa.nLength = sizeof(SECURITY_ATTRIBUTES) ;
   _Sa.lpSecurityDescriptor = NULL ;
   _Sa.bInheritHandle = TRUE ;

   _bResult = CreatePipe(&_hStdInPipeRead,&_hStdInPipeWrite,&_Sa,0) ;
   if(!_bResult) return(NULL) ;

   _bResult = CreatePipe(&_hStdOutPipeRead,&_hStdOutPipeWrite,&_Sa,0) ;
   if(!_bResult) return(NULL) ;

   GetEnvironmentVariable("ComSpec",_szComSpec,sizeof(_szComSpec)) ;
   sqlite3_snprintf(sizeof(_szCommand),_szCommand,"%s /c \"%s\"",_szComSpec,__lpszCommand) ;

   _Si.cb = sizeof(STARTUPINFO) ;
   _Si.dwFlags = STARTF_USESTDHANDLES ;
   _Si.hStdError = _hStdOutPipeWrite ;
   _Si.hStdOutput = _hStdOutPipeWrite ;
   _Si.hStdInput = _hStdInPipeRead ;

   if(CreateProcess(NULL,_szCommand,NULL,NULL,TRUE,CREATE_NO_WINDOW,NULL,__lpszDirectory,&_Si,&_Pi))
   {
      while(WaitForSingleObject(_Pi.hProcess,5) == WAIT_TIMEOUT)
      {
         MSG _uMsg ;

         if(PeekMessage(&_uMsg,NULL,0,0,PM_REMOVE))
         {
            TranslateMessage(&_uMsg) ;
            DispatchMessage(&_uMsg) ;
         }
      }

      CloseHandle(_hStdOutPipeWrite) ;
      CloseHandle(_hStdInPipeRead) ;

      _lpszBuffer = MemoryAlloc(65536) ;
      if(_lpszBuffer)
         FileRead(_hStdOutPipeRead,(unsigned char *) _lpszBuffer,65536) ;

      CloseHandle(_hStdOutPipeRead) ;
      CloseHandle(_hStdInPipeWrite) ;

      CloseHandle(_Pi.hProcess) ;
      CloseHandle(_Pi.hThread) ;
   }

   return(_lpszBuffer) ;
}


How to call it.


   _lpszCompilation = ShellHelper(_lpszBuildFileName,_lpszProjectDirectory) ; // execute the build command
   if(_lpszCompilation)
   {
      _lpszResult = _szResult ;
      sqlite3_snprintf(sizeof(_szResult),_lpszResult,"%s\\StdOut.txt",_lpszProjectDirectory) ; // secure wsprintf
      _hFile = CreateFile(_lpszResult,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL) ;
      FileWrite(_hFile,(unsigned char *) _lpszCompilation,lstrlen(_lpszCompilation)) ; // Write the stdout buffer
      CloseHandle(_hFile) ;
      MemoryFree(_lpszCompilation) ; // frees the memory (VirtualFree)
      File_FileReadExt(_lpszResult,TRUE) ; // for openning a text window in readonly mode
   }


The result of the stdout file

Quote
C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release>"C:\Program Files\PellesC\Bin\porc.exe" -N -L0x40c -I"C:\Program Files\PellesC\Include\Win" -I"C:\Program Files\PellesC\Include" "C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.rc" -Fo"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.res"

C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release>"C:\Program Files\PellesC\Bin\pocc.exe" -std:C17 -Tx64-coff -Gd -W2 -arch:SSE2 -Ot -Ox -Ob2 -I"C:\Program Files\PellesC\Include\Win" -I"C:\Program Files\PellesC\Include" -fp:precise -Ze -Zx -J "C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c" -Fo"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.obj"
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(47): warning #2118: Parameter '__lParam' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(96): warning #2118: Parameter '__CodeNotify' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(96): warning #2118: Parameter '__hWndCtl' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(106): warning #2118: Parameter '__hWnd' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(113): warning #2118: Parameter '__hWnd' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(120): warning #2118: Parameter '__dwNewHeight' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(120): warning #2118: Parameter '__dwNewWidth' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(120): warning #2118: Parameter '__hWnd' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(141): warning #2118: Parameter '__lpszCmdLine' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(141): warning #2118: Parameter '__hPrevInstance' is not referenced.
C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c(120): warning #2135: Static 'Main_OnSize' is not referenced.

C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release>"C:\Program Files\PellesC\Bin\polink.exe" -subsystem:windows -nxcompat -machine:x64 -release -LIBPATH:"C:\Program Files\PellesC\Lib\Win64" -LIBPATH:"C:\Program Files\PellesC\Lib" @"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.rsp" -out:"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.exe" -map:"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.map"
********************************
* Program created successfully *
********************************
Exiting Code 0

Here is the cmd file passed to ShellHelper


"C:\Program Files\PellesC\Bin\porc.exe" -N -L0x40c -I"C:\Program Files\PellesC\Include\Win" -I"C:\Program Files\PellesC\Include" "C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.rc" -Fo"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.res"
@IF ERRORLEVEL 1 GOTO ERRPORC

"C:\Program Files\PellesC\Bin\pocc.exe" -std:C17 -Tx64-coff -Gd -W2 -arch:SSE2 -Ot -Ox -Ob2 -I"C:\Program Files\PellesC\Include\Win" -I"C:\Program Files\PellesC\Include" -fp:precise -Ze -Zx -J "C:\Users\Philippe\Documents\Pelles C Projects\myApp\myApp.c" -Fo"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.obj"
@IF ERRORLEVEL 1 GOTO ERRPOCC

"C:\Program Files\PellesC\Bin\polink.exe" -subsystem:windows -nxcompat -machine:x64 -release -LIBPATH:"C:\Program Files\PellesC\Lib\Win64" -LIBPATH:"C:\Program Files\PellesC\Lib" @"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.rsp" -out:"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.exe" -map:"C:\Users\Philippe\Documents\Pelles C Projects\myApp\Release\myApp.map"
@IF ERRORLEVEL 1 GOTO ERRPOLINK

@GOTO SUCCESS
:ERRPORC
@ECHO ===========================
@ECHO === Errors found (PORC) ===
@ECHO ===========================
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 5
@ECHO Exiting Code 5
@GOTO FINISHED
:ERRPOASM
@ECHO ============================
@ECHO === Errors found (POASM) ===
@ECHO ============================
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 4
@ECHO Exiting Code 4
@GOTO FINISHED
:ERRPOCC
@ECHO ===========================
@ECHO === Errors found (POCC) ===
@ECHO ===========================
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 3
@ECHO Exiting Code 3
@GOTO FINISHED
:ERRPOLINK
@ECHO =============================
@ECHO === Errors found (POLINK) ===
@ECHO =============================
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 2
@ECHO Exiting Code 2
@GOTO FINISHED
:ERRPOLIB
@ECHO ============================
@ECHO === Errors found (POLIB) ===
@ECHO ============================
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 1
@ECHO Exiting Code 1
@GOTO FINISHED
:SUCCESS
@ECHO ********************************
@ECHO * Program created successfully *
@ECHO ********************************
@IF EXIST .\AfterBuild.cmd @CALL .\AfterBuild.cmd 0
@ECHO Exiting Code 0
@GOTO FINISHED
:FINISHED
@ECHO ON
@EXIT