ARM汇编实现10!陷入死循环求助:保留代码结构修复错误
修复ARM汇编阶乘代码的死循环问题
问题分析
你遇到的死循环核心原因是栈地址配置错误:原代码中SRAM_BASE EQU 0x40000000并非多数ARM芯片的可写SRAM起始地址,导致栈操作无法正确保存/恢复lr寄存器。执行LDMFD sp!, {r4, pc}时,pc被加载了错误的返回地址,从而陷入死循环。
循环本身的逻辑是正确的,通过条件指令实现了从n到1的累乘,但栈地址的错误导致函数无法正常返回。
修复后的代码(保留原结构与注释)
AREA Reset, CODE, READONLY ENTRY SRAM_BASE EQU 0x20000000 ; 修改为Cortex-M系列通用SRAM起始地址,需根据实际芯片调整 EXPORT Reset_Handler Reset_Handler ; Set the stack memory location. LDR sp, =SRAM_BASE + 0x1000 ; 增大栈空间,避免溢出风险 ; Pass the function parameter n value as 10 using the MOV command to the register that holds the parameter. MOV r0, #10 ; Insert the code that calls the function to calculate factorial. The function name is CalcFacto in this case. BL CalcFacto ; Verify the returned value using the register that received the value, and exit the program. stop B stop CalcFacto ; while callee-saved registers are used to store values that must be preserved and include r4-r11 and lr. ; Save r4 and lr registers that will be used for calculation on the stack using stack operation commands. STMFD sp!, {r4, lr} MOV r4, #1 ; n = 0 , n! = 1 CMP r0, #0 ; compare if n value is 0 sub_loop ; perform multiplication operation using loop until n value becomes 0 ; store the multiplication result in r4 MULGT r4, r4, r0 ; Compare if the value obtained by subtracting 1 from the n value is greater than 0. SUBGTS r0, r0, #1 ; Branch to loop if the n value is greater than 0 BGT sub_loop ; Return the result value as per AAPCS using r0 and r1 registers. MOV r0,r4 ; At the end of the function, restore the value of the r4 register, and store the lr register value as PC to return. LDMFD sp!, {r4, pc} END
关键修复说明
- 修正SRAM地址:将
SRAM_BASE改为0x20000000(多数Cortex-M芯片的SRAM起始地址),如果使用其他架构芯片,需替换为对应硬件的可写SRAM起始地址。 - 增大栈空间:将栈起始地址从
SRAM_BASE + 100改为SRAM_BASE + 0x1000,避免栈溢出风险(原100字节空间虽足够,但预留更多空间更稳妥)。 - 正常返回逻辑:执行完
CalcFacto后跳回stop B stop是预期的程序终止逻辑,并非错误,用于让程序停在断点处方便查看结果。
内容的提问来源于stack exchange,提问作者CheshireZzz
相关产品推荐
相关产品推荐

