What is the difference between the struct approach and the stack frame approach other than keeping R/EBP free? Maybe I misunderstand. I have seen examples of GCC (32bits) output producing stack frames, so it still seems a legitimate technique.
Currently in the SharpBASIC compiler the stack cleanup is done after the function call, as it was also messed up with the push instructions before the call. Seems more logical to me, but it's a matter of opinion. Here is a simple, stupid example I used to test function calls in the expression parser:
' SharpBASIC function
' -------------------
incl "lib/sys.sbi";
decl func five(n: int8): int8;
dim sum: int8;
main do
sum = five(5 * 5) + five(5 + 5);
print sum;
end;
func five(n: int8): int8
do
five = n;
end;
Generated asm code (without any code optimizations):
SECTION .text
global _start
global _end
_start:
movsx eax, byte [_C3]
push eax
movsx eax, byte [_C3]
pop edx
imul edx
push eax
call _I26
add esp, 4
push eax
movsx eax, byte [_C3]
push eax
movsx eax, byte [_C3]
pop edx
add eax, edx
push eax
call _I26
add esp, 4
pop edx
add eax, edx
; save sum
mov [_I27], al
; load sum
movsx eax, byte [_I27]
; print int
mov ebx, _sb_buf12
call _sb_intstr
call _sb_print
call _sb_printlf
_end:
mov ebx, 0
mov eax, 1
int 80h
_I26:
push ebp
mov ebp, esp
sub esp, 4
; init func five
mov byte [ebp - 4], 0
; load n
movsx eax, byte [ebp + 8]
; save func result five
mov [ebp - 4], al
._L0:
; load func result five
movsx eax, byte [ebp - 4]
mov esp, ebp
pop ebp
ret
extern _sb_intstr
extern _sb_print
extern _sb_printlf
extern _sb_buf12
SECTION .rodata
_C3 db 5
SECTION .bss
; define sum
_I27 resb 1
When you say Pascal compiler, which compiler do you mean? There are several of them, both commercial and free. Same goes for C compilers.