x86 Assembly Language: Filling an array with values generated by a subroutine
编辑:非常感谢您的帮助!我真的很感激它,因为出于某种原因,我在概念化装配时遇到了一些麻烦,但我正在将它们拼凑在一起。
1) 我正在使用调试器逐行执行。问题,Project2.exe 中 0x0033366B 处的未处理异常:0xC0000005:访问冲突写入位置 0x00335FF8 发生在此行:
1 | mov [arrayfib + ebp*4], edx |
我认为这可能是因为主过程无法访问来自另一个循环的 return 语句,但不确定 - 很难理解这里发生了什么。
2) 我添加了额外的评论,希望能更清楚地说明这一点。对于上下文:我已经链接了我用来访问斐波那契数的模型,我的目标是用值填充这个数组,从最后一个循环到第一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | .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\t\t\t\t\t\t\t\t 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\t\t\t\t\t\t\t\t\t\t mov eax, 0\t\t\t\t\t\t\t\t\t\t mov edi, 1\t ;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\t\t\t\t\t\t\t\t\t\t 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 |
你的斐波那契函数破坏 EBP,返回小于零。
如果您的数组位于页面的开头,则
所以这正是发生的情况:当您的
(在典型的调用约定中,函数调用破坏它们的寄存器参数是正常的,尽管使用 EBP 进行参数传递是不寻常的。通常在 Windows 上,你会在 ECX 和/或 EDX 中传递参数,然后返回在 EAX 中。或者在堆栈上,但这对性能来说很糟糕。)
(还有很多其他的东西对你的斐波那契函数也没有意义,例如我认为你想要
在汇编语言中,每条指令对架构状态(寄存器值和内存内容)都有特定的影响。您可以在指令集参考手册中查找此效果,例如 https://www.felixcloutier.com/x86/index.html。
没有"魔法"可以为您保留寄存器。 (好吧,如果您编写 如果您希望函数保留其调用方的 EBP 值,则需要以这种方式编写函数。 (例如 maybe this because the return statement from the other loop is not able to be accessed by the main procedure 这没有任何意义。