I've written another example program in AEC, this time it's printing the Pascal's Traingle:
Now there are 7 example programs in the ZIP archive. It's kind of a symbolic number, I think I'll stop there for some time. I've also slightly refactored the "permutations" example to make it easier to read.
Code:
;Pascal's triangle
AsmStart ;Inline assembly in AEC starts with "AsmStart" and ends with "AsmEnd".
macro pushIntegerToTheSystemStack decimalNumber ;This is why I've chosen FlatAssembler for the back-end of my compiler: powerful and easy-to-use preprocessor.
{
sub esp,4 ;"esp" is the CPU register which points right below the data at the top of the system stack.
fld dword [decimalNumber]
fistp dword [esp] ;"fistp" is the x86 assembly language directive for converting decimal numbers to integers.
}
macro pushPointerToTheSystemStack pointer
{
sub esp,4
lea ebx,[pointer]
mov [esp],ebx
}
macro pushStringToTheSystemStack string
{
sub esp,4
mov dword [esp],string
}
format PE console ;"PE" means 32-bit Windows executable.
entry start
include 'win32a.inc' ;FlatAssembler macros for importing functions from DLLs.
section '.text' code executable
start:
jmp howManyRowsString$
howManyRowsString:
db "How many rows of Pascal's triangle do you want to be printed?",10,0 ;10 is '\n', and 0 is '\0'.
howManyRowsString$:
pushStringToTheSystemStack howManyRowsString
call [printf] ;printf(howManyRowsString)
jmp theFloatSymbol$
theFloatSymbol:
db "%f",0
theFloatSymbol$:
pushPointerToTheSystemStack numberOfRows
pushStringToTheSystemStack theFloatSymbol
call [scanf] ;scanf(theFloatSymbol,&numberOfRows)
AsmEnd
currentRow := 0
While currentRow < numberOfRows | currentRow = numberOfRows
AsmStart
jmp currentRowString$
currentRowString:
db "Row #%d:",9,0 ;9 is '\t' (the tabulator).
currentRowString$:
pushIntegerToTheSystemStack currentRow
pushStringToTheSystemStack currentRowString
call [printf] ;printf(currentRowString,currentRow)
AsmEnd
currentColumn:=0
While currentColumn < currentRow | currentColumn = currentRow
If currentColumn = 0
array (currentRow * numberOfRows + currentColumn) := 1 ;When I haven't programmed the compiler to deal with 2-dimensional arrays...
ElseIf currentColumn = currentRow
array (currentRow * numberOfRows + currentColumn) := 1
Else
numberImmediatelyAbove := array ( (currentRow - 1) * numberOfRows + currentColumn)
numberBeforeTheImmediatelyAboveOne := array ( (currentRow - 1) * numberOfRows + currentColumn - 1)
array (currentRow * numberOfRows + currentColumn) := numberBeforeTheImmediatelyAboveOne + numberImmediatelyAbove
EndIf
numberToBePrinted := array (currentRow * numberOfRows + currentColumn)
AsmStart
jmp integerSignWithTabulator$
integerSignWithTabulator:
db "%.0f",9,0 ;"%.0f\t", "%.0f" means for "printf" to round the decimal number to the nearest integer.
integerSignWithTabulator$:
fld dword [numberToBePrinted]
fstp qword [esp] ;"qword" means "double", because "printf" from "MSVCRT.DLL" can't print "float" which hasn't been converted to "double". When writing in Assembly, you need to deal with that kind of annoying stuff.
pushStringToTheSystemStack integerSignWithTabulator
call [printf] ;printf(integerSignWithTabulator,numberToBePrinted)
AsmEnd
currentColumn := currentColumn + 1
EndWhile
AsmStart
jmp newLineString$
newLineString:
db 10,0 ;"\n"
newLineString$:
pushStringToTheSystemStack newLineString
call [printf] ;printf(newLineString)
AsmEnd
currentRow := currentRow + 1
EndWhile
AsmStart
pushStringToTheSystemStack pauseString
call [system] ;system(pauseString), the "Press any key to continue..." message so that the console window doesn't immediately close.
invoke exit,0 ;exit(0)
pauseString db "PAUSE",0
section '.rdata' readable writable
result dd ? ;A variable used internally by the AEC compiler.
numberOfRows dd ?
currentRow dd ?
currentColumn dd ?
numberBeforeTheImmediatelyAboveOne dd ?
numberImmediatelyAbove dd ?
numberToBePrinted dd ?
array dd 30000 DUP(?)
section '.idata' data readable import
library msvcrt,'msvcrt.dll' ;"Microsoft Visual C Runtime Library", available as "C:\Windows\System32\msvcrt.dll" on Windows 98 and newer.
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf',clock,'clock'
AsmEnd