Когда вы выполняете call
, адрес следующей операции помещается в стек как возвращаемое значение.При создании функции часто принято создавать «кадр стека».Этот кадр можно использовать для печати стека вызовов, а также смещения для локальных переменных и аргументов.Кадр создается с помощью двух операций в начале функции:
push ebp
mov ebp, esp
В конце функции стек вызовов удаляется с использованием leave
, что эквивалентно обратному выполнению этих двух операций.,При использовании фрейма стека значение esp
сохраняется в ebp
, что указывает на местоположение в стеке, называемое основанием фрейма.Поскольку выше этого адреса есть старое значение ebp
и адрес возврата, вы обычно получите первый аргумент, используя [ebp+8]
.Однако вы не установили фрейм стека.Это означает, что старое значение ebp
не было помещено в стек, а текущее значение ebp
нельзя использовать для получения аргументов, поскольку вы не знаете, где оно находится.Поэтому вы должны получить аргумент, используя [esp+4]
.
Кроме того, обычно возвращаемые значения помещаются в eax
и ebx
сохраняется для вызывающей стороны.Ваш код не соответствует ни одному из этих соглашений.Кроме того, технически функции не требуются для сохранения ecx
или edx
, поэтому обычно вы должны помещать их в стек перед вызовом другой функции, если вы хотите, чтобы они были сохранены.С помощью этого кода edx
и ebx
будут перезаписаны, если их вызвать со значением, превышающим 2, что приведет к неверному результату.
Вот полный список, который включает все упомянутые мной исправления.Я не создал фрейм стека, так как он не нужен, а ваш код этого не сделал.