В настоящее время я изучаю основы языка ассемблера для ОС LINUX, процессоров x84-64, компиляторов GCC, и я натолкнулся на пример, который пытается перевести в сборку следующую функцию C:
unsigned long fact(unsigned n)
{
if (n<=1)
return 1;
else
return n*fact(n-1);
}
ThisЭто предложенное решение:
.intel_syntax noprefix
.text
.global fact
.type fact, @function
fact: PUSH RBP
MOV RBP, RSP
CMP EDI, 1
JBE retour_un
PUSH RDI
DEC RDI
SUB RSP, 8
CALL fact
ADD RSP, 8
POP RDI
MUL RDI
JMP retour
retour_un: MOV RAX, 1
retour: POP RBP
RET
Однако я не совсем понимаю, как это работает.Из того, что я прочитал, инструкция CALL помещает в стек значение RIP, а затем переходит туда, где его аргумент показывает.В этом случае я понимаю до того момента, когда используется факт CALL.Если эта инструкция реализуется каждый раз, то программа запускается с начала до тех пор, пока RDI == 1, в этом случае она перейдет к retour_un, и все, что находится между ними, никогда не будет выполнено.Может кто-нибудь объяснить мне, где я ошибаюсь и как на самом деле работает этот фрагмент кода сборки?