x86 Jeśli utworzysz ramkę stosu, to pierwszy przykład przedstawia zmienne lokalne znajdujące się w funkcji.
push ebp
mov ebp, esp
sub esp, 8
mov dword[ebp-4], 1
mov dword[ebp-8], 2
; ...
mov esp, ebp
pop ebp
retn 8
Natomiast drugi przykład oznacza argumenty funkcji.
push ebp
mov ebp, esp
sub esp, 8
mov dword[ebp+8], 1
mov dword[ebp+12], 2
; ...
mov esp, ebp
pop ebp
retn 8
Jest to przydatne, jeśli chcesz wywoływać tę samą funkcję z różnymi argumentami, czyli np.
(defun sum-1 (a b)
(+ a b)) ; => SUM-1
(sum-1 5 9) ; => 14
(sum-1 10 2) ; => 12
; Common Lisp
Bazując na zmiennych lokalnych byłoby to niemożliwe.
Poniżej kod konkatenacji dwóch łańcuchów znaków, nie wiem czy poprawnie napisany, ponieważ za bardzo nie testowałem.
global _main
extern _printf
section .data
fmt_c: db "%c", 0
fmt_s: db "%s", 0
fmt_n: db "%hhu", 0
s1: db "abcdef_as", 0
s2: db "123def", 0
s3: db "flower", 0
section .text
_main:
push ebp
mov ebp, esp
sub esp, 8
mov dword[ebp+8], s1
mov dword[ebp+12], s2
call concat
push eax
push fmt_s
call _printf
add esp, 8
mov esp, ebp
pop ebp
retn 8
concat:
mov eax, dword[ebp+8]
lea eax, [eax]
call len_s
mov esi, ecx
mov ebx, dword[ebp+12]
lea ebx, [ebx]
dec ebx
mov ecx, 0
l2:
xor edx, edx
inc ebx
mov dl, [ebx]
mov edi, ecx
add ecx, esi
mov word[eax+ecx], dx
mov ecx, edi
inc ecx
cmp ecx, esi
jne l2
ret
len_s:
mov ecx, -1
l1:
inc ecx
cmp byte[eax+ecx], 0x00
jne l1
ret
Kompilacja pod Windows (10) - assembler NASM.
nasm -fwin32 concat.asm && gcc concat.obj -o concat.exe && concat.exe
Prototyp funkcji (jest to już gotowa napisana funkcja) np. w Common Lisp wygląda tak
(let ((source-1 "abcdef_as")
(destination-1 "123def"))
(concatenate 'string source-1 destination-1)) ; => abcdef_as123def