Как указали @dyukha и @Daniel H, возвращаемое значение равно «что есть в вашем EAX
регистре».Ваша функция завершается с for
-циклом, следовательно, последняя инструкция, выполненная перед возвратом (завершением функции), вероятно, была тестом ветвления, чтобы проверить, если i <= n
(ваше условие цикла).На самом деле вы можете проверить, какая переменная установлена в вашем регистре EAX
, используя ваш компилятор для генерации версии сборки вашего кода (опция -S
).Вы можете попытаться проследить, какие значения установлены в вашем регистре, перед вызовом
popq %rbp
retq
в конце вашей функции.
На моем компьютере я пытался использовать Apple LLVM версии 9.0.0 (clang-900.0.39.2), который генерирует следующее для моей функции:
movl %edi, -8(%rbp)
movl %esi, -12(%rbp)
movl $1, -20(%rbp)
movl $1, -16(%rbp)
LBB2_1: ## =>This Inner Loop Header: Depth=1
movl -12(%rbp), %eax
cmpl -16(%rbp), %eax
jl LBB2_4
## BB#2: ## in Loop: Header=BB2_1 Depth=1
movl -20(%rbp), %eax
imull -8(%rbp), %eax
movl %eax, -20(%rbp)
## BB#3: ## in Loop: Header=BB2_1 Depth=1
movl -16(%rbp), %eax
addl $1, %eax
movl %eax, -16(%rbp)
jmp LBB2_1
LBB2_4:
movl -4(%rbp), %eax
popq %rbp
retq
Как видите, у меня есть 4 замечательных адреса: -8(%rbp)
, -12(%rbp)
, -16(%rbp)
и -20(%rbp)
.Учитывая порядок объявления в коде C и порядок инициализации, -8(%rbp)
равно base
, -12(%rbp)
равно n
, -16(%rbp)
равно i
и -20(%rbp)
равно p
.
LBB2_1
- это состояние вашей петли.Инструкции для проверки: * переместить значение n
в %eax
* - это значение на %eax
ниже значения i
, сохранить результат в %eax
*, если %eax
говорит, что оно былониже, перейдите к метке LBB2_4
иначе перейдите к следующей инструкции
Три инструкции после BB # 2 - это фактическое умножение.Три инструкции после BB # 3 - это ваш прирост i
, за которым следует безусловный переход к условию вашего цикла в метке LBB2_1
.
Окончание функции power состоит в том, чтобы взять все, что находится вадрес памяти -4(%rbp)
, положить его в %eax
, а затем оставить функцию (сбросить указатель стека, поместить значение в %eax
в соответствующую переменную в предыдущем кадре стека).
В кодесозданный моим компилятором, я не вижу того же результата, что и вы, так как я получаю каждый раз, когда последние два столбца равны 0 (-4(%rbp)
никогда не устанавливается на что-либо).За исключением случаев добавления вызова к другой функции foo
, принимая два целых числа в качестве параметров, имея две локальные целочисленные переменные (чтобы гарантировать, что мой новый кадр стека будет иметь тот же размер, что и степенная функция).Эта функция фактически устанавливает адрес -4(%rbp)
.При вызове моей функции непосредственно перед входом в цикл я нахожу значение из -4(%rbp)
, установленное в моей функции foo
, возвращаемое в моей функции power
.
Как только что сказал мне коллега, играя снеопределенное поведение опасно, так как вашему компилятору разрешено обращаться с ним любым удобным для него способом.Это может быть вызов демона во что бы то ни стало.
В окончательном, или TL; DR, это неопределенное поведение обрабатывается компилятором в некоторым образом .Независимо от того, перемещено ли какое-либо значение из одной локальной переменной, определено или нет, или ничего особенного не перемещено в регистр %eax
, зависит от компилятора.В любом случае, все, что там висело, возвращалось, когда вызывали retq
.