A programming language implementation for fun.
This code uses the most cutting edge feature set of the language. In some cases there is a known bug where one byte isn't returned properly, this is likely a stack misalignment error which I never got around to fixing.
// You can include standard libc functions
extern printf
extern memcpy
// This function returns an array of 13 bytes
#gen_arr:->u8(13):
// Declare an array of 13 bytes with uninitialized data
buf : u8(13) = _
// Typical C style three section for loop
for (i : i32 = 0, i < 13, i++):
// This uses some pointer arithmetic to assign values to the bytes in the array
$(@buf + i) = i
end
// return the buffer from the function
ret buf // This function takes two arrays of 13 bytes each and prints them
#printarr:(arr: u8(13)),(arr2:u8(13)):
for (i : i32 = 0, i < 13, i++):
// Call the standard printf using all the normal format specifiers.
// Use some pointer arithmetic to get the values from the byte arrays
[printf "arr %d => %d :: %d\n", i, $(@arr+i), $(@arr2 + i)]
end
// Print out the memory address differences as an example
[printf "address difference: %d\n", (@arr2 - @arr)]
ret
// This is the typical C equivalent main function.
#main:
// Call the printarr function passing in the return value of gen_arr for each argument.
// The compiler handles moving all the memory around for us!
[printarr [gen_arr], [gen_arr]]
ret
This then can be converted into executable machine code using the nasm tool. NOTE: The comments are auto generated by the compiler based on the source code.
BITS 32globalmainexternmemcpy ; Make sure we always have thisexternprintfexternmemcpysection .data__str0: db 'arr %d => %d :: %d',0xA,0__str1: db 'address difference: %d',0xA,0section .text;function declaration gen_arrgen_arr:pushebpmovebp,espsubesp,16;variable i=0push DWORD 0 ; Push 0popeaxmov[ebp-20],eaxsubesp,4 ; make room for scope variables.__for_0:; loop conditionpush DWORD [ebp-20] ; Push i valuepush DWORD 13 ; Push 13; LSS expressionpopedxpopeaxcmpeax,edxsetl alpusheaxpopeax ; eax now has result of condition (either 0 or 1)cmpeax,0 ; check if condition was true or falseje .__forend_natural_0; for body;variable defref exprpush DWORD [ebp-20] ; Push i valueleaeax,[ebp-16]; Get address of bufpusheax; push address onto stackpush DWORD [ebp-20] ; Push i valuepopedx ; Get Rightpopeax ; Get leftaddeax,edx; Addpusheax ; Push resultpopedx ; Load addresspopeax ; Load valuemov[edx],al ; type sensitive write; incrementor.__forinc_0:inc DWORD [ebp-20] ; Increment i; jump to start of loopjmp .__for_0.__forend_natural_0:addesp,4 ; pop natural for scope.__forend_0:; copy array onto stacksubesp,16movedx,esppush16leaeax,[ebp-16]pusheaxpushedxcall memcpyaddesp,12movedx,esp ; Compute stack addresspush16 ; Push sizepushedx; Push src*leaedx,[ebp+8] ; Compute address of return spacepushedx ; Push dst*call memcpyaddesp,12addesp,16 ; clean up special stackmoveax,edx ; Move address of special stack into eax;returnmovesp,ebppopebpret;end function gen_arr;function declaration printarr2printarr2:pushebpmovebp,espsubesp,0;variable i=0push DWORD 0 ; Push 0popeaxmov[ebp-4],eaxsubesp,4 ; make room for scope variables.__for_1:; loop conditionpush DWORD [ebp-4] ; Push i valuepush DWORD 13 ; Push 13; LSS expressionpopedxpopeaxcmpeax,edxsetl alpusheaxpopeax ; eax now has result of condition (either 0 or 1)cmpeax,0 ; check if condition was true or falseje .__forend_natural_1; for bodyleaeax,[ebp+20]; Get address of arr2pusheax; push address onto stackpush DWORD [ebp-4] ; Push i valuepopedx ; Get Rightpopeax ; Get leftaddeax,edx; Addpusheax ; Push resultpopeax ; Load addressmovzxeax, BYTE [eax] ; Type sensitive Readpusheax ; Push Valueleaeax,[ebp+4]; Get address of arrpusheax; push address onto stackpush DWORD [ebp-4] ; Push i valuepopedx ; Get Rightpopeax ; Get leftaddeax,edx; Addpusheax ; Push resultpopeax ; Load addressmovzxeax, BYTE [eax] ; Type sensitive Readpusheax ; Push Valuepush DWORD [ebp-4] ; Push i valuepush __str0call printfaddesp,16; incrementor.__forinc_1:inc DWORD [ebp-4] ; Increment i; jump to start of loopjmp .__for_1.__forend_natural_1:addesp,4 ; pop natural for scope.__forend_1:leaeax,[ebp+20]; Get address of arr2pusheax; push address onto stackleaeax,[ebp+4]; Get address of arrpusheax; push address onto stackpopedx ; Get Rightpopeax ; Get Leftsubeax,edx ; Subtractpusheax ; Push resultpush __str1call printfaddesp,8;returnmovesp,ebppopebpret;end function printarr2;function declaration mainmain:pushebpmovebp,espsubesp,0subesp,16 ; Push space for return typepushesp ; push return space pointer as hidden first parametercall gen_arraddesp,4subesp,16 ; Push space for return typepushesp ; push return space pointer as hidden first parametercall gen_arraddesp,4call printarr2addesp,8;returnmovesp,ebppopebpret;end function main