You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raspberry Pi 4汇编实现随机数发生器出现段错误求助

汇编实现LFSR随机数发生器触发段错误的问题

我用汇编实现了基于LFSR的随机数发生器,通过Vim编写代码、GCC编译运行,但始终触发段错误(Segmentation Fault)。GDB调试显示错误发生在set_leds函数,回溯指向generate_random分支处。我已用Python脚本验证GPIO引脚功能正常,也尝试过重建文件目录、拆分代码排查,问题仍未解决。

以下是我的汇编代码:

.section .data 
seed: .word OxA5A5A5A5 // Initial seed for the LFSR 
.section .text .global main 
main: 
// Start and initialization of the seed 
LDR RO, =seed // Load address of seed into RO 
LDR R1, [RO] // Load seed value into R1 
generate_random:
// Perform LFSR 
LSR R2, R1, #1 // Logical shift right 
AND R3, R1, #1 // AND with 1 to get LSB 
EOR R2, R2, R3, LSL #31 // XOR with LSB shifted to MSB 
MOV R1, R2 // Move result back to R1 
// Store new seed 
STR R1, [RO] // Store updated seed back to memory 
// Use lower bits of the seed to determine LED output 
AND R4, R1, #0xFF // Mask lower 8 bits 
BL set_leds // Branch to set_leds function 

wait_button: // Wait for button press 
LDR R5, =0xFE200000 // Base address 
ADD R6, R5, #0x34 // GPIO Pin Level Register 
LDR R6, [R6] // Load GPIO level register 
LDR R7, =0x0400 // Load constant (1 << 10) into R7 
AND R6, R6, R7 // Check GPIO pin 10 (button) 
BEQ wait_button 
// Loop until button is pressed 
// Delay loop for debouncing 
MOV R7, #0x3F0000 // Load delay value 
delay_loop: 
SUBS R7, R7, #1 // Decrement delay counter 
BNE delay_loop // Loop until delay is finished 
B generate_random // Go back to generate_random

// Function to set the LEDs 
set_leds: 
PUSH {R4-R7, LR} // Save the return address and used registers 
// Setup for the GPIO 
LDR R6, =0xFE200000 // Base address for GPIO on Raspberry Pi 4 
// Set GPIO pins 2-9 to output 
LDR R7, =0x000003FC // Load constant (0b11111111 << 2) into R7 
STR R7, [R6, #0x04] // Set as output 
// Clear the GPIO pins 
LDR R7, =0x000003FC // Load constant (Ob11111111 << 2) into R7 
STR R7, [R6, #0x28] // Clear the pins 
// Set the GPIO pins based on R4 
MOV R7, R4 
AND R7, R7, #0xFF 
LDR R8, =0x000000FC // Load constant (0b11111111 << 2) into R8 
ORR R7, R7, R8 
STR R7, [R6, #0x1C] // Set the pins 
POP {R4-R7, LR} // Restore the registers and return address 
BX LR 
// Return from function

问题排查与修复方案

1. 寄存器拼写错误

代码中多处将ARM寄存器R0误写为RO(字母O),这会导致程序访问错误的寄存器,进而操作非法内存地址,直接触发段错误。需将所有RO替换为R0。

2. 立即数拼写错误

初始种子OxA5A5A5A5使用了字母O开头,正确的十六进制前缀应为数字0,需修正为0xA5A5A5A5。

3. 代码段语法错误

.section .text .global main属于语法错误,需拆分为两行:

.section .text
.global main

否则汇编器无法正确识别全局符号定义,导致程序入口异常。

4. 寄存器上下文破坏

set_leds函数中使用了R8寄存器,但PUSH/POP列表中未包含R8。根据ARM APCS调用规范,R4-R11属于非临时寄存器,必须在函数开头保存、结尾恢复,否则会破坏调用者的上下文。需修改栈操作指令:

PUSH {R4-R8, LR}
// ...函数代码...
POP {R4-R8, LR}

5. GPIO控制逻辑错误

原代码中通过ORR R7, R7, R8设置LED引脚的逻辑错误,正确做法是将R4的低8位直接左移2位,映射到GPIO2-9的位置:

MOV R7, R4
AND R7, R7, #0xFF
LSL R7, R7, #2  // 将低8位移到GPIO2-9对应的位
STR R7, [R6, #0x1C]

6. 运行权限问题

Raspberry Pi的GPIO寄存器属于硬件资源,普通用户无访问权限,必须以root权限运行程序,否则会触发段错误。运行时需执行:

sudo ./你的程序名

修复后的完整代码

.section .data 
seed: .word 0xA5A5A5A5 // 修正立即数拼写错误
.section .text 
.global main // 拆分语法错误的行
main: 
// 初始化种子
LDR R0, =seed // 修正RO为R0
LDR R1, [R0] // 修正RO为R0
generate_random:
// LFSR生成随机数
LSR R2, R1, #1 
AND R3, R1, #1 
EOR R2, R2, R3, LSL #31 
MOV R1, R2 
// 保存新种子
STR R1, [R0] // 修正RO为R0
// 获取低8位用于LED控制
AND R4, R1, #0xFF 
BL set_leds 

wait_button: // 等待按键按下
LDR R5, =0xFE200000 
ADD R6, R5, #0x34 
LDR R6, [R6] 
LDR R7, =0x0400 
AND R6, R6, R7 
BEQ wait_button 
// 消抖延迟
MOV R7, #0x3F0000 
delay_loop: 
SUBS R7, R7, #1 
BNE delay_loop 
B generate_random

// LED控制函数
set_leds: 
PUSH {R4-R8, LR} // 新增保存R8
LDR R6, =0xFE200000 
// 设置GPIO 2-9为输出
LDR R7, =0x000003FC 
STR R7, [R6, #0x04] 
// 清除引脚状态
LDR R7, =0x000003FC 
STR R7, [R6, #0x28] 
// 根据R4设置引脚
MOV R7, R4 
AND R7, R7, #0xFF 
LSL R7, R7, #2 // 把低8位移到GPIO2-9的位置
STR R7, [R6, #0x1C] 
POP {R4-R8, LR} // 恢复R8
BX LR 

内容的提问来源于stack exchange,提问作者Raging Storm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:30:19