NO

Author Topic: Simple console piping example  (Read 7243 times)

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Simple console piping example
« on: January 22, 2012, 11:25:39 AM »
Here is a simple console pipe example. The executable pipe.exe reads data from STDIN and converts it to uppercase.

Code: [Select]
dir /b | pipe

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

Code: [Select]
pipe "This is a test"

THIS IS A TEST

Source code :

Code: [Select]
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

  • Guest
Re: Simple console piping example
« Reply #1 on: January 23, 2012, 08:24:45 PM »
Very nice.

CLR

  • Guest
Re: Simple console piping example
« Reply #2 on: January 23, 2012, 08:50:20 PM »
Where is @f, @b? Oh I miss the basics

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: Simple console piping example
« Reply #3 on: January 24, 2012, 07:14:21 AM »
From PellesC help:
Command line tools -> POASM macro assembler -> Introduction -> Special code labels:
Quote
Special 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.
« Last Edit: January 24, 2012, 10:24:23 AM by timovjl »
May the source be with you

CLR

  • Guest
Re: Simple console piping example
« Reply #4 on: January 24, 2012, 02:34:23 PM »
Thank you timovjl

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: Simple console piping example
« Reply #5 on: January 24, 2012, 09:49:08 PM »
Hi CLR,

Thanks for your kind words.

You can replace anonymous labels with regular ones :

Code: [Select]
_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

  • Guest
Re: Simple console piping example
« Reply #6 on: January 27, 2012, 05:27:07 PM »
OK. Thank you Vortex.

Grincheux

  • Guest
Re: Simple console piping example
« Reply #7 on: January 07, 2020, 06:42:58 PM »
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.

Code: [Select]
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.

Code: [Select]
   _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

Code: [Select]
"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
« Last Edit: January 07, 2020, 06:48:15 PM by Grincheux »