Ваша функция Фибоначчи уничтожает EBP, возвращая с ним значение меньше нуля.
Если ваш массив находится в начале страницы, тогда arrafib + ebp*4]
попытается получить доступ к предыдущей странице и произойдет сбой. Обратите внимание на адрес ошибки 0x00335FF8
- последние 3 шестнадцатеричных цифры - это смещение в виртуальной странице 4k, 0x...3FF8
= 0x...4000 + 4*-2
.
Так что именно так и произошло: EBP = -2, когдаВаше mov
хранилище выполнено.
(Обычно вызовы функций уничтожают свои аргументы регистров в типичных соглашениях о вызовах, хотя использование EBP для передачи аргументов непривычно. Обычно в Windows вы передаете аргументы в ECX и/ или EDX, и возвращаемся в EAX. Или в стеке, но это отстой в производительности.)
(Есть много других вещей, которые тоже не имеют смысла в вашей функции Фибоначчи, например, я думаю, что выхочу jmp L1
, а не loop L1
, что похоже на dec ecx / jnz L1 без установочных флагов.
В языке ассемблера каждая инструкция имеет определенный эффект на архитектурное состояние (значения регистров и содержимое памяти). Вы можете посмотреть на этот эффект в справочном руководстве по набору инструкций, например https://www.felixcloutier.com/x86/index.html.
Нет "магии", которая сохраняет регистры для вас. (Ну, MASM будет толкать / выдавать за вас, если вы напишете что-то вроде proc foo uses EBP
, но пока вы не поймете, что это делает для вас, лучше , а не , чтобы ассемблер добавил инструкции в ваш код.)
Если вы хотите, чтобы функция сохранила значение EBP своего вызывающего, вам нужно написать функцию таким образом. (например, mov
, чтобы скопировать значение в другой регистр.) См. Что такое сохраненные регистры вызывающего и вызывающего абонентов? для получения дополнительной информации об этой идее.
может быть, потому что оператор returnиз другого цикла недоступна основная процедура
Это не имеет никакого смысла.
ret
- это то, как мы пишем pop eip
. Нелокальных эффектов нет, вам просто нужно убедиться, что ESP указывает на адрес (нажатие на вызов), к которому вы хотите перейти. Ака обратный адрес.