Edit: Thank you so much for all your help! I really appreciate it because for some reason I am having some trouble conceptualizing assembly but I'm piecing it together.
1) I am using the debugger to step through line by line. The problem, Unhandled exception at 0x0033366B in Project2.exe: 0xC0000005: Access violation writing location 0x00335FF8 occurs at this line:
mov [arrayfib + ebp*4], edx
Is think maybe this because the return statement from the other loop is not able to be accessed by the main procedure, but not sure - having a hard time understanding what is happening here.
2) I have added additional comments, hopefully making this somewhat clearer. For context: I've linked the model I've used to access the Fibonacci numbers, and my goal is to fill this array with the values, looping from last to first.
.386 .model flat, stdcall .stack 4096 INCLUDE Irvine32.inc ExitProcess PROTO, dwExitCode: DWORD .data arrayfib DWORD 35 DUP (99h) COMMENT ! eax = used to calculate fibonacci numbers edi = also used to calculate fibonacci numbers ebp = number of fibonacci sequence being calculated edx = return value of fibonacci number requested ! .code main PROC ;stores n'th value to calculate fibonacci sequence to mov ebp, 30 mov edx, 0 ;recursive call to fibonacci sequence procedure call FibSequence mov [arrayfib + ebp*4], edx dec ebp jnz FibSequence mov esi, OFFSET arrayfib mov ecx, LENGTHOF arrayfib mov ebx, TYPE arrayfib call DumpMem INVOKE ExitProcess, 0 main ENDP ;initializes 0 and 1 as first two fibonacci numbers FibSequence PROC mov eax, 0 mov edi, 1 ;subrracts 2 from fibonacci number to be calculated. if less than 0, jumps to finish, ;else adds two previous fibonacci numbers together L1: sub ebp, 2 cmp ebp, 0 js FINISH add eax, edi add edi, eax LOOP L1 ;stores odd fibonacci numbers FINISH: test eax, 1 jz FINISHEVEN mov edx, eax ret ;stores even fibonacci numbers FINISHEVEN: mov edx, edi ret FibSequence ENDP END main
Your Fibonacci function destroys EBP, returning with it less than zero.
If your array is at the start of a page, then
arrafib + ebp*4] will try to access the previous page and fault. Note the fault address of
0x00335FF8 - the last 3 hex digits are the offset within a 4k virtual page, an
0x...4000 + 4*-2.
So this is exactly what happened: EBP = -2 when your
mov store executed.
(It's normal for function calls to destroy their register args in typical calling conventions, although using EBP for arg-passing is unusual. Normally on Windows you'd pass args in ECX and/or EDX, and return in EAX. Or on the stack, but that sucks for performance.)
(There's a lot of other stuff that doesn't make sense about your Fibonacci function too, e.g. I think you want
jmp L1 not
loop L1 which is like dec ecx / jnz L1 without setting flags).
In assembly language, every instruction has a specific effect on the architectural state (register values and memory contents). You can look up this effect in an instruction-set reference manual like https://www.felixcloutier.com/x86/index.html.
There is no "magic" that preserves registers for you. (Well, MASM will push/pop for you if you write stuff like
proc foo uses EBP, but until you understand what that's doing for you it's better not to have the assembler adding instructions to you code.)
If you want a function to preserve its caller's EBP value, you need to write the function that way. (e.g.
mov to copy the value to another register.) See What are callee and caller saved registers? for more about this idea.
maybe this because the return statement from the other loop is not able to be accessed by the main procedure
That doesn't make any sense.
ret is just how we write
pop eip. There are no non-local effects, you just have to make sure that ESP is pointing to the address (pushed by call) that you want to jump to. Aka the return address.
User contributions licensed under CC BY-SA 3.0