I have. I call it AEC (Arithmetic Expression Compiler). I've designed it to be extremely low-level and integrate as seamlessly as possible with Assembly. The compiler makes no assumptions about the operating system, it simply outputs i486-compatible assembly for arithmetic expressions and expects you to do everything else in assembly (including variable declarations and setting up the system stack).
Here are my first two programs written in it:
Code: Select all
;So, this was my first program written in my own programming language. I call it AEC.
;Warning: The comments about arrays don't apply to this version of AEC any more. See "fibonacci.aec" for more information!
AsmStart ;This part of code is Windows-dependent, so it has to be done in inline assembly.
debug=0
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
AsmEnd
i:=1
j:=1
While i<101
j:=1
While j<101
AsmStart
if debug=1 ;Invoking FlatAssembler preprocessor.
fld dword [j]
fstp qword [esp+12]
fld dword [i]
fstp qword [esp+4]
mov dword [esp],_debugOutput1
call [printf]
end if
AsmEnd
If i>j
a:=i
b:=j
Else
a:=j
b:=i
EndIf
While (b>1/100)&(a>1/100) ;Modified version of the Euclid's algorithm.
If a>b
a:=mod(a,b)
Else
b:=mod(b,a)
EndIf
EndWhile ;There is a reason why BASIC used different keywords for "EndIf" and "EndWhile", because they are trivial to translate to Assembly :-).
subscript:=i*101+j
If a>1/100
gcd[subscript]:=a ;Warning: Arrays are write-only in this version of AEC, they have to be read in inline Assembly. Hopefully that's not too hard.
Else
gcd[subscript]:=b
EndIf
AsmStart
if debug=1
fld dword [a]
fstp qword [esp+20]
fld dword [j]
fstp qword [esp+12]
fld dword [i]
fstp qword [esp+4]
mov dword [esp],_debugOutput2
call [printf]
mov dword [esp],_pause
call [system]
end if
AsmEnd
j:=j+1
EndWhile
i:=i+1
EndWhile
AsmStart
mov dword [esp],_output1
call [printf]
mov dword [esp+4],firstNumber
mov dword [esp],_input1
call [scanf]
mov dword [esp],_output2
call [printf]
mov dword [esp+4],secondNumber
mov dword [esp],_input1
call [scanf]
fild dword [firstNumber]
fstp dword [a]
fild dword [secondNumber]
fstp dword [b]
AsmEnd
subscript:=4*(a*101+b) ;While you need to use inline Assembly to read arrays, you can still calculate subscripts in AEC.
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
fld dword [gcd+ebx]
fst qword [esp+4]
mov dword [esp],_output3
call [printf]
invoke system,_pause
invoke exit,0
_debugOutput1 db "DEBUG: Attempting to calculate the GCD of %f and %f.",10,0
_debugOutput2 db "DEBUG: GCD of %f and %f is %f.",10,0
_output1 db "Enter the first number (whole number 1-100): ",0
_input1 db "%d",0
_output2 db "Enter the second number (whole number 1-100): ",0
_pause db "PAUSE",0
_output3 db "Their greatest common divisor is: %f",10,0
section '.rdata' readable writable ;Yes, you are expected to declare the variables yourself in inline assembly, as the way it's done varies greatly from one operating system to another.
result dd ?
a dd ?
b dd ?
i dd ?
j dd ?
firstNumber dd ?
secondNumber dd ?
subscript dd ?
gcd dd 101*101 dup(?)
section '.idata' data readable import ;Those functions can't be called from this version of AEC (as the way to call them in Assembly varies from one operating system to another), they have to be called from inline Assembly.
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
AsmEnd
Code: Select all
;So, this is my second program in my own programming language.
AsmStart
debug=0
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
mov dword [esp],_output1
call [printf]
mov dword [esp+4],n
mov dword [esp],_input1
call [scanf]
AsmEnd
fib(0):=0
fib(1):=1
i:=2
While i<n+1
fib(i):=fib(i-1)+fib(i-2) ;Good idea, QBASIC! Treating Assembly arrays as functions, I would have never thought of that! It's really easy to program.
i:=i+1
EndWhile
subscript:=(i-1)*4
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
fld dword [fib+ebx]
fstp qword [esp+4]
mov dword [esp],_output2
call [printf]
mov dword [esp],_pause
call [system]
mov dword [esp],0
call [exit]
_output1 db "Enter n (0-100): ",0
_output2 db "The n-th Fibonacci number is: %f",10,0
_input1 db "%f",0
_pause db "PAUSE",0
section '.rdata' readable writable
result dd ? ;Yes, you need to declare it to be used internally by AEC. Hope you don't mind! :-)
n dd ?
i dd ?
subscript dd ?
fib dd 100 dup(?)
section '.idata' data readable import
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
AsmEnd
You can try it here (yes, the native version is a little hard to install right now, and the on-line version doesn't have all the features because of the limitations imposed by browsers for security reasons):
http://flatassembler.000webhostapp.com/compiler.html
To make all the features it has now, I used seven programming languages, some of which I've first used there (C, Assembly, JavaScript, HTML, CSS, PHP and some SVG).
Do you have some similar experience?