Pelles C forum
Assembly language => Assembly discussions => Topic started by: Vortex 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.
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
-
Very nice.
-
Where is @f, @b? Oh I miss the basics
-
From PellesC help:
Command line tools -> POASM macro assembler -> Introduction -> Special code labels:
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.
-
Thank you timovjl
-
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
-
OK. Thank you Vortex.
-
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
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