Другие языки программирования и технологии

Как реализовать рекурсию на языке ассемблера? (intel 80х86, masm, tasm или fasm)

Не так уж и сложно. Почти так же, как и в языках высокого уровня. Только в ЯВУ этот механизм скрыт от программиста.
Для хранения локальных переменных используется системный стек. Если для передаваемых параметров не хватает регистров, то их тоже передают через стек.
Пример рекурсивной функции с реализацией модели вызова stdcall в TASM для 16-разрядного режима:

recursive proc
;Локальные переменные с символическими метками
local1 equ [ bp-2 ];локальная переменная №1
local2 equ [ bp-4 ];локальная переменная №2
;Символические метки на передаваемые параметры (передаются, как const)
const1 equ [ bp+6 ];переменная №1
const2 equ [ bp+4 ];переменная №2
;формирование фрейма стека для хранения локальных переменных
push bp
mov bp,sp
sub sp,4
...
mov local1,ax;Запись в локальную переменную №1
add ax,const2;Использование входной переменной №2
mov dx,const1;Загрузка входной переменной №1
push ax;Передача переменной №1 для рекурсии
push dx;Передача переменной №2 для рекурсии
call recursive
mov local2,ax;сохранение возвращённого результата в лок. переменную №2
...
mov ax,local2
sub ax,local1;В ах результат выполнения функции
mov sp,bp;Уничтожение фрейма стека (локальных переменных)
pop bp
ret 4;Возврат с уничтожением переданных параметров (восстановление стека согласно stdcall)

;Вызов рекурсивной функции из тела основной программы
mov bx,1234h
push bx; загрузка первой переменной
mov si,56ABh
push si; загрузка второй переменной
call recursive;Вызов рекурсии. Результат вернётся в ax

Для 32-разрядного режима всё так же с учётом разрядности:
recursive proc
;Локальные переменные с символическими метками
local1 equ [ ebp-4 ];локальная переменная №1
local2 equ [ ebp-8 ];локальная переменная №2
;Символические метки на передаваемые параметры (передаются, как const)
const1 equ [ ebp+12 ];переменная №1
const2 equ [ ebp+8 ];переменная №2
;формирование фрейма стека для хранения локальных переменных
push ebp
mov ebp,esp
sub esp,8
...
mov local1,eax;Запись в локальную переменную №1
add eax,const2;Использование входной переменной №2
mov edx,const1;Загрузка входной переменной №1
push eax;Передача переменной №1 для рекурсии
push edx;Передача переменной №2 для рекурсии
call recursive
mov local2,eax;сохранение возвращённого результата в лок. переменную №2
...
mov eax,local2
sub eax,local1;В eах результат выполнения функции
mov esp,ebp;Уничтожение фрейма стека (локальных переменных)
pop ebp
ret 8;Возврат с уничтожением переданных параметров (восстановление стека согласно stdcall)

;Вызов рекурсивной функции из тела основной программы
mov ebx,12345670h
push ebx; загрузка первой переменной
mov esi,56AB3C61h
push esi; загрузка второй переменной
call recursive;Вызов рекурсии. Результат вернётся в eax
Петя Макар
Петя Макар
51 590
Лучший ответ
Константин Чекенёв спасибо, а стек получается отчищается вызванной процедурой? Т.е. вызывающий вообще не парится?
Что то вроде такого. На входе EСX = число, на выходе в EAX - факториал
factorial:
xor eax, eax
inc eax
fact:
cmp ecx, 1
je theend
imul ecx
dec ecx
call fact
theend:
ret
Антон Гейд
Антон Гейд
12 551
ассемблер учил давно, по этому синтаксис помню не очень, но как и в любом другом языке программирования, просто вызывай функцию из функции
Константин Чекенёв В ассемблере нет поддержки рекурсии, параметры процедур затираются, ассемблер это не си и даже не фортран и прямой поддержки рекурсии в нём нет, нужно реализовывать ручками.
вот, что-то делал, уже не помню что.
brainFuck proc
arg depth:word
pushbp
movbp,sp
pushsi
pushax
pushbx
pushcx
pushdx
pushdi

movcx,number
salcx,1
xor si,si
cycle:
movdi,si
adddi,depth
incdi
cmpdi,cx
jgeoutofcyc
cmp[mas_number+si],0
jne outofcyc
cmp[mas_number+di],0
jneoutofcyc

movax,depth
mov[mas_number+si],al
mov[mas_number+di],al

cmpax,number
jnep_else

xor si,si
cyc2:moval,[mas_number+si]
mov[finish_number+si],al
incsi
cmpsi,cx
jlcyc2
jmpreturnfrom
p_else:
movbx,depth
incbx
pushbx
callbrainFuck
mov[mas_number+si],0
mov[mas_number+di],0
outofcyc:
incsi
cmpsi,cx
jlcycle
returnfrom:
popdi
popdx
popcx
popbx
popax
popsi
popbp
ret[2]

endp
Максим Лут
Максим Лут
584
Константин Чекенёв Вооот. Наконец. В дуре 1 параметр word, передаётся через стек да?