Понимание сборки рекурсивной функции - PullRequest
0 голосов
/ 29 декабря 2011

Я изучаю ассемблер, и у меня есть эта функция, содержащая несколько строк, которые я просто не понимаю:

. globl
. text

factR:
 cmpl $0 ,4(% esp )
 jne cont
 movl $1 ,%eax
 ret

cont :
 movl 4(%esp),%eax
 decl %eax
 pushl %eax          // (1)
 call factR          // (2)
 addl $4,%esp        // (3)
 imull 4(%esp),%eax 
 ret

и соответствующий ему код C:

int factR ( int n ) {
    if ( n != 0 )
        return n;
    else
        return n ∗ factR ( n − 1 );
}

Я не уверен насчет линий, помеченных цифрами.

  1. pushl %eax: означает ли это, что мы помещаем содержимое %eax в %esp

  2. Итак, мы называем factR(). Будет ли результат этого в %esp, когда мы вернемся сюда к следующим инструкциям?

  3. addl $4,%esp не уверены насчет этого, мы добавляем 4 к числу, хранящемуся в %esp, или мы добавляем 4 к указателю, чтобы получить следующий номер или что-то подобное?

1 Ответ

3 голосов
/ 29 декабря 2011

Похоже, что функция factR() соответствует соглашению о вызовах C ( cdecl ).Именно здесь вызывающая сторона помещает аргументы вызова функции в стек, а вызывающая сторона очищает стек (отменяет изменения в стеке, сделанные для вызова функции)когда функция возвращает значение.

Первое нажатие (1) помещает содержимое регистра %eax в качестве аргумента для следующего вызова.Затем выполняется фактический вызов функции (2).Затем стек очищается (3) путем сброса указателя стека %esp обратно в состояние, когда аргумент не был передан обратно на шаге 1. Он сдвинул одно 32-битное значение, поэтому он должен отрегулировать указатель на 4-байт.

...