x86 MASM汇编中数组大小导致斐波那契输出垃圾值问题
问题原因与解决方案
问题根源
- 你的
.data段中,array和fib变量连续存放,fib紧跟在array之后。fib是一个存储数组基地址的DWORD变量,而你通过[fib + esi * 4]访问数组元素时,每次都会先读取fib存储的基地址再计算偏移。 - 当
array设为41个DWORD元素时,数组占用41*4=164字节。循环中esi增大到特定值(如esi=41)时,计算出的偏移地址会恰好指向fib变量本身的位置。此时执行mov [fib + esi * 4], eax会把fib中存储的数组基地址覆盖成当前斐波那契数值,后续访问数组时使用的是被篡改的错误基地址,自然会读出垃圾值。 - 数组越大,
fib离array末尾越远,计算前41个斐波那契数的偏移地址碰不到fib的位置,因此不会出现覆盖问题,结果正确。
修复方法
以下两种方式任选其一,即可将数组设为41个元素并得到全部正确结果:
方式1:调整变量顺序
将fib变量移到array前面,确保数组的偏移永远不会覆盖fib:
.data display BYTE "Fibonacci number ", 0 equal BYTE " = ", 0 fib DWORD OFFSET array ; 将fib移到array之前 array DWORD 41 DUP(0) ; 设为41个元素
方式2:用寄存器存储数组基地址
直接用寄存器(如EBX)存储数组基地址,避免使用.data段变量带来的覆盖风险,同时提升代码效率:
INCLUDE Irvine32.inc .data display BYTE "Fibonacci number ", 0 equal BYTE " = ", 0 array DWORD 41 DUP(0) ; 设为41个元素 .code main PROC mov ebx, OFFSET array ; 用EBX存储数组基地址 mov [ebx], 0 mov [ebx + 4], 1 mov [ebx + 8], 1 mov ecx, 3 mov esi, 0 L1: mov edx, OFFSET display call WriteString mov eax, esi call WriteDec mov edx, OFFSET equal call WriteString mov eax, [ebx + esi * 4] call WriteDec call Crlf inc esi loop L1 mov ecx, 38 mov esi, 3 Fibo: mov edx, OFFSET display call WriteString mov eax, esi call WriteDec mov edx, OFFSET equal call WriteString mov eax, [ebx + esi * 4 - 4] add eax, [ebx + esi * 4 - 8] mov [ebx + esi * 4], eax mov eax, [ebx + esi * 4] call WriteDec inc esi call Crlf loop Fibo exit main ENDP end main
内容的提问来源于stack exchange,提问作者newGuy77
相关产品推荐
相关产品推荐

