Страница 1 из 1

Рекурсия в asm процедуре\функции[Решено]

СообщениеДобавлено: 13.03.2011 17:50:28
Maxizar
Собственно хотел спросить, как это реализовывать, во всех книгах по ассемблеру, пишут именно про ассемблерные функции, в которых есть вызов CALL и возврат RET.
А как быть с функциями, более высокого уровня.? Нигде об этом нормально не написано, по этому решил спросить.
Методом изучения исходников (асм кода) который генерирует FPC с ключами типа:
Код: Выделить всё
-Amasm -al –s

Сделал вывод, что вызов происходит с указанием имени функции при помощи CALL.
Провел эксперимент:
Функция расчета факториала:
Код: Выделить всё
function Factorial(AValue: Cardinal): Cardinal;
begin
  if AValue <=1 then
    Result:=1
    else
      Result:=AValue*Factorial(AValue-1)
end;


Она же переписанная мною на асм:
Код: Выделить всё
function Factorial2(AValue: Cardinal): Cardinal; register;assembler;
{$ASMMODE Intel}
  asm
    cmp eax,1         //Сравниваем AValue с 1
    jg @Biger1        //Если AValue>=1 то переходим на @Biger1

    mov eax,1          //Иначе вернем 1
    jmp @Exit          // и Выдем

  @Biger1:
    push eax           //Сохраняем eax иначе затрем его в дальнейшем
    dec eax
    call Factorial2    //Вызываем процедуру в eax уже лежит AValue-1
    pop ecx            //Вернем, то что положили в функции  Factorial2
    mul ecx            //умножим на eax.

  @Exit:
  end;     

Проверка:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
Caption:=IntToStr(Factorial(5));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
   Caption:=IntToStr(Factorial2(5));
end;

Дает верный результат….

Вопрос: Получается что вызов функции, по идее сопровождается простым вызовом оператора CALL. Но до этого мы как бы сами должны приготовить входные параметры ? Скажем у меня все просто нужно только положить число в EAX…(потому что Avalue должно лежать там)и просто вызвать функцию, после вызова, нужно знать где будет лежать результат… Для процедур которые используют параметры из стека (pascal вызов) мы сами должны будем приготовить стек…?
Но мы получается используем стек одной и той же функции… или это так и происходит, Не будет ли переполнения?...

Вопрос №2:
Вот если это так, например просто не понятно, что вложить в стек в этом случае...Различие стека в Delphi and FPC что за результ ($Result) там лежит….
в той теме было сказано что:
Kvasshtain писал(а):Но я считаю, что это банальный ЖУЧОК. Или точнее всего не жучок, а его кривое исправление . Т.е. они (разработчики) скорее всего чо то там сначала напутали, а потом исправили, но немножко криво. А может это какая то внутренняя особенность Лазарыча (ну типа что то вроде какая-то там дополнительная инфа по выполнению процедуры/функции в стек заносится, а чо за инфа и как она им используется, история типа умалчивает, или ищем не там где надо ). Вот мое ИМХО

Если это баг или неизвестно что туда положить, можно пока обойтись соглошением register. Но чтобы это работало хотябы при соглашении register, я должен разобраться с вопросом №1.

Спасибо за любые наводки по этому вопросу…

Re: Рекурсия в asm процедуре\функции

СообщениеДобавлено: 13.03.2011 18:57:50
Sergei I. Gorelkin
1) Да, вызывающая сторона должна приготовить параметры в соотвествии с типом вызова вызываемой стороны. Стек один на всех, и при глубокой рекурсии переполнение вполне возможно, даже если туда не класть ничего лишнего - просто за счет того, что инструкция CALL помещает в стек адрес возврата.

2) Вызываемая сторона может использовать стек по своему усмотрению, при условии что она: а) не трогает того, что там лежало до нее, б) закончив свою бурную деятельность, возвратит указатель стека на исходное место. А вызывающая сторона кладет параметры совершенно независимо от того, что туда потом положит вызываемая сторона.

Re: Рекурсия в asm процедуре\функции[Решено]

СообщениеДобавлено: 13.03.2011 20:28:23
Maxizar
Спасибо.
Теперь я готов чтобы переписать функцию расчета БПФ, под асм :D