This program is designated for demonstration and testing of the base functions from 64bit Windows Application Binary Interface macrolibrary winabi.htm : WinABI, GetArgCount, GetArg, GetEnv, StdInput, StdOutput, TerminateProgram.
%StdConsole %SETB Yes ; Set StdOutput Console mode, which displays ANSI and WIDE strings correctly.
EUROASM CPU=X64,SIMD=Enabled
EUROASM UNICODE=Yes ; or UNICODE=No. twinabi can be assembled in any Unicode mode.
twinabi PROGRAM Format=PE,Width=64,Entry=Main:
INCLUDE winabi.htm, cpuext%^WIDTH.htm
Main: PROC
%IF %^UNICODE
%CharMode %SET WIDE
%ELSE
%CharMode %SET ANSI
%ENDIF
StdOutput ="twinabi.exe is demo of macrolibrary winabi.htm assembled in %CharMode mode.",Eol=Yes
; Test GetArg, display count and values of arguments from command line:
GetArgCount ; Count the command-line arguments.
JC .Abort:
MOV [ArgCount],RCX
MOV EAX,ECX
StoD ArgCount$ ; Convert binary number RAX to a decimal ANSI string.
JC .Abort:
StdOutput Eol=Yes
StdOutput =B"%^PROGRAM launched with ", ArgCount$, =B" arguments:", Unicode=No, Eol=Yes
JC .Abort:
SUB EBX,EBX ; EBX will be the ordinal number of each argument.
.EchoArg: CMP RBX,[ArgCount]
JA .EchoEnv: ; Jump when all arguments have been echoed.
MOV EAX,EBX
StoD ArgNr$ ; Convert binary number RAX to a decimal ANSI string.
SUB EAX,EAX
STOSB ; Zero-terminate the argument ordinal number.
GetArg RBX ; Retrieve RBX-th argument to RSI,RCX.
JC .Abort:
MOV EAX,ECX ; Argument size in bytes.
StoD ArgSize$ ; Convert binary number RAX to a decimal string.
SUB EAX,EAX
STOSB ; Zero-terminate the argument size.
StdOutput ArgNr$, =B".[", ArgSize$, =B"]: ", Unicode=No
StdOutput RSI, Size=RCX, Eol=Yes ; Echo the argument value.
JC .Abort:
INC EBX
JMP .EchoArg:
; Test PutEnv, display value of three variables, their retrieved (ECX) and required (EAX) size:
.EchoEnv: StdOutput Eol=Yes
StdOutput ='Environment strings:', Eol=Yes
envNr %FOR 1,2,3
StdOutput EnvName%envNr,=" [",
PutEnv EnvName%envNr,EnvVal%envNr
PUSHF
PUSH RCX
StoD ReqSize$ ; Convert binary number RAX to a decimal ANSI string.
SUB EAX,EAX
STOSB
POP RAX
StoD EnvSize$ ; Convert binary number RAX to a decimal ANSI string.
SUB EAX,EAX
STOSB
StdOutput EnvSize$,=B" retrieved, ",ReqSize$,=B" required]: ",Unicode=No
POPF
JC .Bad%envNr
StdOutput EnvVal%envNr,Eol=Yes
JMP .Next%envNr:
.Bad%envNr:StdOutput =B" is too big or not found.",Eol=Yes,Unicode=No
.Next%envNr:
%ENDFOR envNr
; Test StdInput and StdOutput with four combinations of ANSI/WIDE and File/Console access method:
StdOutput Eol=Yes
StdOutput ="Standard input and output demonstration:",Eol=Yes
unicode %FOR No,Yes
console %FOR No,Yes
StdOutput =B"Input/Output mode: Unicode=%unicode, Console=%console", \
Eol=Yes, Console=No, Unicode=No
StdOutput =B"Enter some text: ", Console=No, Unicode=No
StdInput Buffer, Console=%console, Unicode=%unicode
JC .Abort:
MOV EAX,ECX ; Text size including CR+LF.
StoD BufSize$ ; Convert binary number RAX to a decimal string.
SUB EAX,EAX
STOSB ; Zero-terminate the string.
StdOutput =B"Entered[",BufSize$,=B"]: ", Console=No, Unicode=No
StdOutput Buffer, Size=RCX, Eol=Yes, Console=%console, Unicode=%unicode
JC .Abort:
%ENDFOR console
%ENDFOR unicode
StdOutput =B"%^PROGRAM terminated.", Console=No, Unicode=No
TerminateProgram Errorlevel=0
.Abort: StdOutput =B"Aborted, some macro returned CF.",Eol=Yes,Console=No,Unicode=No
TerminateProgram Errorlevel=4
ENDP Main:
EnvName1 D "OS",0
EnvName2 D "PATH",0
EnvName3 D "UNDEFINED",0
EnvVal1 D "1111111111111111",0
EnvVal2 D "2222222222222222",0
EnvVal3 D "3333333333333333",0
ArgCount DQ Q
ArgCount$ DB 8*B
ArgNr$ DB 8*B
ArgSize$ DB 8*B
EnvSize$ DB 8*B
ReqSize$ DB 8*B
BufSize$ DB 8*B
Buffer DB 256*B
ENDPROGRAM twinabi