Encoding Binary files in Batch files

The .mac source code files are for Ass486; Herbert Kleebauer's 68K-like assember

To include com programs into batch files you have to write programs which only uses opcodes in the range 0x20 to 0x7e (without < > | % ^ & " !). Small programs can be directly coded using the processor opcode table. Two examples are ech and myinput:

ech.com is similar to the echo command. It writes the command line after the first " till the penultimate character to stdout (without an trailing CRLF) ech.mac


@echo off
echo XP,;P_,EP0Ex0Ez0Em3Em-ZBP(Eiu![j@_YQ2M@53#@CI~.8'uxCISZ[SC5.bM!C>ech.com
ech.com "line with <>|^&%">tmp.txt
ech.com "but no CRLF">>tmp.txt
del ech.com


myinput.com assigns a keyboard input to batch variable myinput.mac


@echo off
echo BATCH_INPUT___hgQX-PPP_XPPP E#HH0E50EG0Ef0Ehs>myinput.com
echo myinput.bat hoAX5@@PZYh@xX5@D3!r/P[WX,b,-PZh>>myinput.com
echo X3!X2ErP,{,{PYX4=0ErWX,j,-PZh@@X3!=set input>>myinput.com
echo Enter name:
myinput.com
call myinput.bat
del myinput.com
del myinput.bat
echo You entered %input%


For larger programs (more than a few bytes) it is simpler to use a program to convert a normal com program to an ascii-only program. The batch below does this job. NOTE: you must assemble your com program with ORG=0x178 because the first 120 bytes are needed for the decoding routine which is inserted by the convert program. Six bits of the original com program are coded in one ascii-byte, so your program must not exceed 47 kbyte. The decoding routine of the convert program is (just as MYINPUT and ECH) directly written with ascii-only opcodes, the rest of the program is a normal com program, converted by itself to ascii only bytes.
rem - save the lines below as CONVERT.BAT
rem - write a COM program and assemble it with ORG=0x178 (PROG.COM)
rem   (you must not use the standard ORG=0x100 for this com programs!!!!)
rem - enter: CONVERT PROG.COM PROG.BAT
rem - the BATCH file PROG.BAT contains an encoded form of PROG.COM

@echo off
echo Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>bat.com
echo 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>bat.com
echo ??wQ@tyM?WxI?@zA=`Lbw?y_y~?_xA[bz?B_L??oAN`_H?e?as?Fx?pkz?>>bat.com
echo B_}A[aIA]b@MCs?A_rVAgr?\gBGpangV_~r?TO?wGJLy?hKxAG@z?G`L?K>>bat.com
echo K?wQO`LRaRPdwA_by??cxA_bL?@O=Et`x?y_z?P_L?@oXZ`SdBW\ngbTiA>>bat.com
echo _Syi?To_gD_lWPOOnSOOOTg`ODgDCDgLCDgNCDggCDgrKDgtKDgWKDYdKT>>bat.com
echo \QQTDDDTQXTTCqWP}=w@s`aTnbmSILl@gbdTo_n@EwCTokO@mwWDOosPW=>>bat.com
echo kOrFsTnsAP~c?@xHOTV_TPoWvDTvFTV_XPnzuPWAuTuFqSwDoStHFTusgD>>bat.com
echo a}}Oms`DlnbTdILOngbT}o_?`a}SbmsPLlnD??I??~?OBA@TEDCTHGFTKJ>>bat.com
echo ITNMLTQPOTTSRTWVUTZYXTp\[D`_1TcbaTfedTihgTlkjTonmTrqpTutsT>>bat.com
echo xwvT=zyD?}=D????}}??s`aTnbmSILl@gbdTg_nP0>>bat.com
bat.com <%1 >%2
del bat.com


An example for a program generated with CONVERT is echoo. echoo is similar to echo, but you can also include binary characters by specifying the hex code:
@echo off
echo Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>echoo.com
echo 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>echoo.com
echo ?@xAyJHmH@=a?}VjuN?_LEkS?`w`s_{OCIvJDGEHtc{OCIKGMgELCI?GGg>>echoo.com
echo EL?s?WL`LRBcx=k_K?AxVD?fCo?Cd?BLDs0>>echoo.com

echoo This line contains $3c $3e $7c $25 and $24  $0d$0a
echoo           All leading spaces are removed 
echoo (to get identical results in DOS/Win9x/NT/2000)$0d$0a
echoo $20       insert a explitcit space ($2420) if you want leading spaces. 
del echoo.com


As an other example you can use this method to generate a hex-to-binary converter with ascii-only opcodes. This allows you to include any binary file into a batch file. h2b.com has a string as a parameter. Any line in stdin, starting with this string, is converted from hex to binary and written to stdout.
@echo off
if exist %0.bat %0.bat
echo Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>h2b.com
echo 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>h2b.com
echo ?@}I{uNWEF~NFAa_Lj@KLtH]~CEvEFIKbAa_wN@SuNS`{ECCttasae~BHM>>h2b.com
echo AcjFnvnHAwrvx[}gIKDw??Frt\gqj~{?s?csIsqo{O_KtBve{Sx{nB{Eu@>>h2b.com
echo fq`tkfk?e@oKCA_?_E@?WxAs?agBwRjnLK?s@w`G`LKLAcyA?@xAsZpk`L>>h2b.com
echo ~KxlqLct@vAc_A_yBJ@xAGZp?o?sBXq`LR@xUrFQt=A_E?B?~rB?~r0>>h2b.com

h2b "::f1" <%0 >bild1.gif
h2b "::f2" <%0 >bild2.gif
h2b "::f3" <%0 >demo.com
del h2b.com

:: hex dump of bild1.gif
::f1 4749463839614b001100a20000140b00fffbf7ff6600fffcfa0000000000
::f1 000000000000002c000000004b0011000003a228badcfe30ca0901bd386b
::f1 66b7ff5f078e64242a419aa2eabaa84cebb2731d2cc39357f1cd0ab306ec
::f1 e503fa5cc8e26cc06c30778d53f0e758d988c6c715f7643ca10ae9902abc
::f1 6db35372faebed86cb4399d23c6f917b32079bdb7c576169687354816702
::f1 7b0a887e5a747f79593f8583897d7c0f6258695b9b479d58893a26704976
::f1 909041a493a61e2725ae25adafb2acb3b52100b8b9babbbcbdbebfc0c1bf
::f1 09003b

:: hex dump of bild2.gif
::f2 47494638396121001000b30000fffdfbff6702ffc39aff9e5effdfcaffef
::f2 e5fff8f4ffffffc0c0c00000000000000000000000000000000000000000
::f2 0021f90401000008002c0000000021001000000463f0c849abbd385f3384
::f2 fe9911041e2811432a1499300e00388c743010d83ce26deddf16110d78d1
::f2 f96a1dd6c485e4518ed0a1406044962451a80aa5751eaadd0a73a8a48c8f
::f2 83f2a480548bd1ee892e0d2a4c05841886793581847d7e1f007882862611
::f2 003b

:: hex dump of an executable
::f3 fcbe3301bf4301b95000b020f3aa89fab91000f3a4bbffffb93c00b409cd
::f3 21b40bcd2108c0750801dae2f0f7dbebe9b44ccd21707265737320616e79
::f3 206b65790d0a24


A further method is, to make a dual executable file. Such a file is a valid batch program and a valid com program. You can generate such files with the following batch:
rem - save the lines below as CONVERT.BAT
rem - write a COM program and assemble it with ORG=0x200 (PROG.COM)
rem   (you must not use the standard ORG=0x100 for this com programs!!!!)
rem - enter: CONVERT PROG.COM PROG.BAT
rem - the BATCH file PROG.BAT contains an encoded form of PROG.COM

@echo off
echo Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>ube.com
echo 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>ube.com
echo ??wQ@tyM@CxA?@zA=`Lbw??`y~?_xB{_z?B_L??oAN`_H?e?as?Fx?pkz?>>ube.com
echo B_}A{bIB}_@MCs?A_rVAgr?\gBGpangV_~r?TO?wGJxy?xBxAG@z?G`L?K>>ube.com
echo K?wQO`LRaRPdwB?`y??cxB?`L?@O=Et`x??`z?F_L?@oXZ`S?BW\gBDTN_>>ube.com
echo NPLEEDyyI?M_mOhqNT_brD___?gS_S_rhD_rhDa_`P`mhT_xqDlnbTdg_S>>ube.com
echo dc`T_mq@mnCTLsfCyyI?M_mOteNT__m@___?cd_S_shDdgsThe_SsrqTrp>>ube.com
echo _?hk_SrdmTmh_Sgs_S_rhDkheTLmd@yyI?M_mODcNP?iWTtyiD?`oOOgsO>>ube.com
echo OOOT`OOT`CgChCgCjCgCGCgSRKgSTKgSwKgCnKgCDKgSQQYTDD\TXTDTqW>>ube.com
echo QDOWCTyIL?_my?oWMDEWCTokO@gwWDOssPW=kOrJsTysE@sSsDc?TDHO~S>>ube.com
echo `JxDWUVTVFoS_XTDzUVDAUnTFqWPDoUPHFWTsgtTILk?myy?Lo_??~IOBA>>ube.com
echo @TEDCTHGFTKJITNMLTQPOTTSRTWVUTZYXTp\[D`_1TcbaTfedTihgTlkjT>>ube.com
echo onmTrqpTutsTxwvT=zyD?}=D????IL??myy?my_?0>>ube.com
ube.com <%1 >%2
del ube.com


As an example, here is a binary executable batch header (source code: echadd.mac) which supports 2 functions:

e (echo) and + (increment)

The increment function increments a decimal number by 1.

example: ube.com +123

will write 124 to stdout (note: no space allowed after + and after the number)

The echo function is similar to the standard echo command. The text after the echo command is written to stdout. No <CR> <LF> is appended. You can output any byte by writing the hex value ($3c for < or $0d for <CR> ...). $t writes the current date in the form yymmdd to stdout. After writing the command line text, echo reads from stdin and writes to stdout until a <CR> or <EOF> is read. This byte transfer from stdin to stdout can be modified by subcommands:

The @ must be the first character in the batch file and there must be no trailing spaces in the first 13 lines.


@EChO OFF
::. NOrisc     This is a binary com header. Don't
::. NOfun      edit the first 13 lines in this file.
::. NO$EXj@jz50!@4(PPPPPPa(D!(D)(D+(DH(LS(LU(L8(L/(LEZRR]EEEUYRX2DXP
::. NX0DXFP,0Xx(t4P,=XtKsF4:tT4U@$?PIyK!WVX0GWUY WV;oVBX2GV0EXGIuht,
::. ?A}I{uNWNN}VINw`{ECCus_ssd{Sj{_?B@spNxH]HTw`}@qr?C}bux{OCEFKNMoS
::. gqx=B@GoBYyE?@xAuwNTECIQtk{SE}CK{B_?CttD_M}B1{BO}CtpB`E?tm{OE}CK
::. {Ba?CtyCaM}B_{B?NMt\ICwd{ECCwtcCs{?QNltPisEHH`LbuuGN@BpozGgbgBYp
::. G?PaKgonOG?w?FgJBYyE?ExA?WgJ?@xAgCj~g?Wqg?Tqj?Fqzgx]dq?Ss?H[Y_`X
::. I{B?{osLRsLS_EuBs~B[IxUCq`{Sy{OOjKvp@{GO{Eq@AvYDu_soB`E?Es~Ft_{O
::. 1oAWaEuBs~B[Ix\Ctm{OE}tMjBaom{nA}LtpBaM?EFtpBaE?]j?m?_gBgXjzB?So
::. ????quuBoDB?FHoGpBBDcB?1~sIGLZp{aB`ksBY`@z?H`L?KINBf?Ecc?_KbxVkV
::. C?Bw_?f{_?Co_?Br0

REM ***************** WIN98 batch***************************
REM This batch file will read a word from keyboard,  convert
REM all filenames with this extention to upper case, replace
REM spaces in the filename by _ and insert the current  date 
REM in font of the new filename 

if [%1]==[] goto main
_ <nul e $t%1|_ >>__.bat eu_ $0d$0aren %1 
goto ende

:main
if exist %0 copy %0 _.com
if exist %0.bat copy %0.bat _.com

_ <nul e enter file extention:
_ >__.bat e set ext=
call __.bat
del  __.bat
LFNFOR on
for %%i in (*.%ext%) do call %0 "%%i"
LFNFOR off

del _.com
echo check __.bat and execute it
REM call __

:ende


CM3 (dissassembly CM3.txt)

See also:

Parse a string

:: Parse a string (%str%)
@echo off

:: Set string to parse
set str=some text

echo `h}aXP5y`P]4nP_XW(F4(F6(F=(FF)FH(FL(Fe(FR0FTs*}`A?+,> %temp%.\t1.com
echo fkOU):G*@Crv,*t$HU[rlf~#IubfRfXf(V#fj}fX4{PY$@fPfZsZ$:K0>> %temp%.\t1.com
echo 6$-tH[fHzt'fZJtxP'7:p*_q5b*RJo09Mleb\f7+V(52O-f,`u/\vm(]>> %temp%.\t1.com
echo e.iv+y7(-W:ldwn0V.-Z0I6l3)@f2r=?rV+5lYzH]'=v\{)(c\#>> %temp%.\t1.com
:loop
if "%str%"=="" goto endloop
%temp%.\t1.com %str%> %temp%.\t2.bat
call %temp%.\t2.bat str c

:: Right here, %C% will represent each character
:: from the parsed string
echo "%c%"

goto loop
:endloop
for %%? in (t1.com t2.bat) do del %temp%.\%%?

Process each line of a file

@echo off
if "%1"=="GoTo" goto %2

echo `h}aXP5y`P]4nP_XW(F4(F6(F=(FF)FH(FL(Fe(FR0FTs*}`A?+,> %temp%.\pfx.com
echo fkOU):G*@Crv,*t$HU[rlf~#IubfRfXf(V#fj}fX4{PY$@fPfZsZ$:KrM$>> %temp%.\pfx.com
echo 00rqdO1iI$W?DAj{?_@EuF)1F8b1j$MC?Be.]tI:PAJrff764F0T'}$$5]>> %temp%.\pfx.com
echo 7$MG{Fdl$@i*JtSA$$5d80rL@bB=i{A$'FJDbqJ2Djw}D{1~Eu6=?rV+5l>> %temp%.\pfx.com
echo YzHw8TKc3O}@A$$$)$#>> %temp%.\pfx.com
:: filename.ext is the file to be processed
%temp%.\pfx.com < filename.ext > %temp%.\t1.bat
set P=call %0 GoTo process
:: Set below the variable name where the string should be saved
call %temp%.\t1.bat LINE
set P=
del %temp%.\t1.bat
goto eof

:process
:: On this label, each line from the file to be processed will be
:: once represented by a variable (its name is defined above)
echo LINE=%LINE%
goto eof

:eof

See also: