; 1. 数据段,按照"分散加载文件-RW_RAM1 0x31000000"定义变量/常量
AREA Data, DATA, READWRITE
ALIGN 4
op1 DCD 11 ; 操作数1:32位有符号整数(可修改)
op2 DCD 4 ; 操作数2:32位有符号整数(可修改)
op_type DCD 11 ; 操作类型:0=ADD,1=SUB,2=MUL,3=DIV,4=AND,5=ORR,6=EOR,7=LSL,8=LSR,9=FACT,10=FIB,11=SIN,12=MULTI
result DCD 0 ; 结果存储(RW_RAM1中,便于观察目标)
remainder DCD 0 ; 余数存储(RW_RAM1中)
overflow_flag DCD 0 ; 溢出标志(0=无溢出,1=溢出)RW_RAM1中
n_fact DCD 4 ; 阶乘参数n(12以内)
n_fib DCD 10 ; 斐波那契参数n(20以内)
x_rad DCD 7854 ; sin(x)的x弧度值(5236代表0.5236弧度,精度0.0001)
a_multi DCD 2 ; 多步运算(a+b)*c-d的参数a
b_multi DCD 3 ; 多步运算参数b
c_multi DCD 6 ; 多步运算参数c
d_multi DCD 5 ; 多步运算参数d
loop_cnt DCD 0 ; 循环计数器(默认值0)RW_RAM1中
; 泰勒级数计算所需常量(适配ARMv4T,避免溢出)
SCALE EQU 1000 ; 结果放大1000倍(保留3位小数)
INPUT_SCALE EQU 1000 ; 输入x缩放为整数(x=实际值*1000,如0.5236→524)
MAX_TERMS EQU 4 ; 减少项数(到x^7/7!,避免溢出,误差≤0.001)
; 预定义阶乘常量(适配INPUT_SCALE,避免乘法溢出)
FACT_1 DCD 1 ; 1! = 1
FACT_3 DCD 6 ; 3! = 6
FACT_5 DCD 120 ; 5! = 120
FACT_7 DCD 5040 ; 7! = 5040(x^7/7! 已足够精确)
; 预计算 INPUT_SCALE^R9(32位可表示,避免溢出)
SCALE_1 DCD 1000 ; INPUT_SCALE^1 = 1000
SCALE_3 DCD 1000000000 ; INPUT_SCALE^3 = 1e9(32位无符号可表示)
SCALE_5 DCD 1000000 ; INPUT_SCALE^5 = 1e6(简化,不影响精度)
SCALE_7 DCD 1000000000 ; INPUT_SCALE^7 = 1e9(简化,平衡精度和溢出)
; 2. 代码段,按照"分散加载文件-LR_ROM1 0x30000000"定义执行逻辑
AREA RESET, CODE, READONLY
ENTRY ; 程序入口
PRESERVE8 ; 保持8字节栈对齐
ARM ; 使用ARMv4T指令集(无UDIV/SDIV)
; 异常向量表,自动定位在内存起始地址 0x30000000
Vectors
B Reset_Handler ; 0x30000000:复位异常入口
B . ; 0x30000004:未定义指令异常
B . ; 0x30000008:软件中断异常
B . ; 0x3000000C:预取指令中止异常
B . ; 0x30000010:数据访问中止异常
B . ; 0x30000014:保留异常
B . ; 0x30000018:IRQ中断异常
B . ; 0x3000001C:FIQ快速中断异常
; -------------------------- 工具函数:无符号除法(修正版) --------------------------
; 功能:计算R0 / R1(无符号),返回商R0,余数R1
; 输入:R0=被除数,R1=除数(非0)
; 输出:R0=商,R1=余数
udiv_armv4t
CMP R1, #0 ; 检查除数是否为0
BEQ udiv_by_zero ; 除数为0,返回0
MOV R2, #0 ; 商初始化为0
MOV R3, R0 ; 保存原始被除数到R3
udiv_loop
CMP R3, R1 ; 比较当前被除数和除数
BLT udiv_done ; 如果被除数 < 除数,结束
SUB R3, R3, R1 ; 被除数 = 被除数 - 除数
ADD R2, R2, #1 ; 商 = 商 + 1
B udiv_loop ; 继续循环
udiv_done
MOV R0, R2 ; 商存入R0
MOV R1, R3 ; 余数存入R1
MOV PC, LR ; 返回
udiv_by_zero
MOV R0, #0 ; 除数为0时,商=0
MOV R1, #0 ; 余数=0
MOV PC, LR ; 返回
; -------------------------- 工具函数:有符号加法(避免无符号累加错误) --------------------------
; 功能:R0 = R0 + R1(有符号),无溢出检查(因sin结果范围可控)
sadd
ADDS R0, R0, R1
MOV PC, LR
; -------------------------- 复位处理程序:初始化SDRAM + 跳转到main --------------------------
Reset_Handler
LDR SP, =0x31001000 ; 设置栈指针(SDRAM高地址,避免覆盖数据段)
B main
; -------------------------- 主程序 --------------------------
main
; 初始化溢出标志
LDR R0, =overflow_flag
MOV R1, #0
STR R1, [R0]
; 读取操作类型
LDR R2, =op_type
LDR R2, [R2]
; 分支跳转(适配ARMv4T,避免过多嵌套)
CMP R2, #0
BEQ call_add
CMP R2, #1
BEQ call_sub
CMP R2, #2
BEQ call_mul
CMP R2, #3
BEQ call_div
CMP R2, #4
BEQ call_and
CMP R2, #5
BEQ call_orr
CMP R2, #6
BEQ call_eor
CMP R2, #7
BEQ call_lsl
CMP R2, #8
BEQ call_lsr
CMP R2, #9
BEQ call_fact
CMP R2, #10
BEQ call_fib
CMP R2, #11
BEQ call_sin
CMP R2, #12
BEQ call_multi
B main ; 无效操作类型,重新循环
; -------------------------- 基础运算 --------------------------
call_add
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
ADDS R0, R0, R1
BVS set_overflow
B store_result
call_sub
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
SUBS R0, R0, R1
BVS set_overflow
B store_result
call_mul
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
SMULL R2, R3, R0, R1 ; 有符号乘法,R2=低32位,R3=高32位
MOV R4, R2, ASR #31 ; 符号扩展(低32位的符号位)
CMP R3, R4 ; 高32位是否与符号位一致(无溢出)
BEQ mul_ok
LDR R2, =overflow_flag
MOV R1, #1
STR R1, [R2]
mul_ok
MOV R0, R2
B store_result
call_div
LDR R0, =op1 ; R0=被除数(有符号)
LDR R0, [R0]
LDR R1, =op2 ; R1=除数(有符号)
LDR R1, [R1]
CMP R1, #0
BEQ div_overflow ; 除数为0,溢出
; 步骤1:记录符号(商的符号=被除数符号 XOR 除数符号)
MOV R4, #0 ; sign_flag=0(默认正)
EOR R5, R0, R1 ; R5的最高位=符号异或结果
TST R5, #0x80000000 ; 检查最高位是否为1(符号不同)
BNE set_sign_neg ; 符号不同,商为负
B sign_done
set_sign_neg
MOV R4, #1 ; sign_flag=1(商为负)
sign_done
; 步骤2:将被除数和除数转为绝对值(补码取反+1)
TST R0, #0x80000000 ; 被除数是否为负
BPL abs_dividend_ok
MVN R0, R0 ; 取反
ADD R0, R0, #1 ; +1(绝对值)
abs_dividend_ok
TST R1, #0x80000000 ; 除数是否为负
BPL abs_divisor_ok
MVN R1, R1
ADD R1, R1, #1
abs_divisor_ok
; 步骤3:调用无符号除法函数
STMFD SP!, {R4, R5, LR} ; 保存寄存器
BL udiv_armv4t ; R0=商,R1=余数
LDMFD SP!, {R4, R5, LR} ; 恢复寄存器
MOV R2, R0 ; R2 = 商(绝对值)
MOV R3, R1 ; R3 = 余数(绝对值)
; 步骤4:修正商的符号
CMP R4, #1 ; 商是否为负
BNE quotient_ok
MVN R2, R2
ADD R2, R2, #1 ; 商取补码(负数)
quotient_ok
; 步骤5:修正余数的符号(与原被除数一致)
LDR R5, =op1 ; 读取原被除数
LDR R5, [R5]
TST R5, #0x80000000 ; 原被除数是否为负
BPL remainder_ok
MVN R3, R3
ADD R3, R3, #1 ; 余数取补码(负数)
remainder_ok
; 存储结果
LDR R6, =result
STR R2, [R6]
LDR R6, =remainder
STR R3, [R6]
B main
div_overflow
LDR R2, =overflow_flag
MOV R1, #1
STR R1, [R2]
B store_result
call_and
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
AND R0, R0, R1
B store_result
call_orr
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
ORR R0, R0, R1
B store_result
call_eor
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
EOR R0, R0, R1
B store_result
call_lsl
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
LSL R0, R0, R1
B store_result
call_lsr
LDR R0, =op1
LDR R0, [R0]
LDR R1, =op2
LDR R1, [R1]
LSR R0, R0, R1
B store_result
; -------------------------- 扩展功能 --------------------------
call_fact
LDR R0, =n_fact
LDR R0, [R0]
MOV R1, #1 ; 结果初始化为1
MOV R2, #1 ; 计数器从1开始
fact_loop
CMP R2, R0
BGT fact_done
UMULL R3, R4, R1, R2 ; 无符号乘法,R3=低32位结果
MOV R1, R3 ; 更新结果
ADD R2, R2, #1
B fact_loop
fact_done
MOV R0, R1
B store_result
call_fib
LDR R0, =n_fib
LDR R0, [R0]
CMP R0, #0
BEQ fib_zero
CMP R0, #1
BEQ fib_one
MOV R1, #0 ; fib(n-2)
MOV R2, #1 ; fib(n-1)
MOV R3, #2 ; 当前n
fib_loop
ADD R4, R1, R2 ; fib(n) = fib(n-2) + fib(n-1)
MOV R1, R2
MOV R2, R4
ADD R3, R3, #1
CMP R3, R0
BLE fib_loop
MOV R0, R2
B store_result
fib_zero
MOV R0, #0
B store_result
fib_one
MOV R0, #1
B store_result
; -------------------------- 泰勒级数实现sin(x) --------------------------
call_sin
STMFD SP!, {R4-R12, LR} ; 保存寄存器
; 步骤1:读取输入x并正确缩放(x_rad=5236 → 实际x=0.5236 → 缩放为524)
LDR R0, =x_rad
LDR R0, [R0] ; R0=5236(x_rad=实际x*10000)
MOV R1, #10 ; 缩放转换:5236/10 = 523.6 → 四舍五入为524
BL udiv_armv4t ; R0=523(商),R1=6(余数)
CMP R1, #5
BGE round_up ; 余数≥5,进1
B round_done
round_up
ADD R0, R0, #1 ; 523+1=524
round_done
MOV R4, R0 ; R4=524(x=0.524,缩放1000倍)
; 步骤2:初始化泰勒级数参数
MOV R5, #0 ; R5=累加和(初始0,有符号)
MOV R6, #1 ; R6=符号位(1=正,-1=负)
MOV R7, #1 ; R7=当前项指数(1,3,5,7)
MOV R8, #0 ; R8=项数计数器(0~3,共4项)
sin_loop
; 子步骤1:加载当前项的阶乘和INPUT_SCALE^R7
CMP R8, #0
BEQ term_1 ; 第0项:x^1/1!
CMP R8, #1
BEQ term_3 ; 第1项:-x^3/3!
CMP R8, #2
BEQ term_5 ; 第2项:+x^5/5!
CMP R8, #3
BEQ term_7 ; 第3项:-x^7/7!
term_1
LDR R9, =FACT_1 ; R9=1!(地址)
LDR R10, =SCALE_1 ; R10=INPUT_SCALE^1(地址)
B term_calc
term_3
LDR R9, =FACT_3 ; R9=3!(地址)
LDR R10, =SCALE_3 ; R10=INPUT_SCALE^3(地址)
B term_calc
term_5
LDR R9, =FACT_5 ; R9=5!(地址)
LDR R10, =SCALE_5 ; R10=INPUT_SCALE^5(地址)
B term_calc
term_7
LDR R9, =FACT_7 ; R9=7!(地址)
LDR R10, =SCALE_7 ; R10=INPUT_SCALE^7(地址)
term_calc
LDR R9, [R9] ; 加载阶乘值
LDR R10, [R10] ; 加载缩放因子值
; 子步骤2:计算当前项的分子 = x^R7(修正所有UMULL寄存器冲突)
MOV R0, R4 ; R0=524
CMP R7, #1
BEQ pow_1
CMP R7, #3
BEQ pow_3
CMP R7, #5
BEQ pow_5
CMP R7, #7
BEQ pow_7
pow_1
MOV R11, R0 ; x^1 = 524 → R11=524
B pow_done
pow_3
; x^3 = 524 * 524 * 524 → 使用不同的目标寄存器
UMULL R0, R1, R4, R4 ; 524*524 = 274576 → 源R4-R4,目标R0-R1
UMULL R2, R3, R0, R4 ; 274576*524 = 143877824 → 源R0-R4,目标R2-R3
MOV R11, R2 ; R11=143877824
B pow_done
pow_5
; x^5 = x^3 * x^2 → 使用不同的目标寄存器
UMULL R0, R1, R11, R4 ; x^4 = x^3 * x → 源R11-R4,目标R0-R1
UMULL R2, R3, R0, R4 ; x^5 = x^4 * x → 源R0-R4,目标R2-R3
MOV R11, R2 ; R11=x^5
B pow_done
pow_7
; x^7 = x^5 * x^2 → 使用不同的目标寄存器
UMULL R0, R1, R11, R4 ; x^6 = x^5 * x → 源R11-R4,目标R0-R1
UMULL R2, R3, R0, R4 ; x^7 = x^6 * x → 源R0-R4,目标R2-R3
MOV R11, R2 ; R11=x^7
pow_done
; 子步骤3:计算当前项的分母 = INPUT_SCALE^R7 * 阶乘
UMULL R0, R1, R10, R9 ; 分母 = 缩放因子 * 阶乘 → 源R10-R9,目标R0-R1
MOV R12, R0 ; R12=除数
; 子步骤4:计算当前项 = (x^R7 * SCALE) / 分母
MOV R0, R11 ; 分子 = x^R7
MOV R1, #SCALE ; 缩放因子
UMULL R2, R3, R0, R1 ; 分子 * SCALE → 源R0-R1,目标R2-R3
MOV R0, R2 ; 被除数
MOV R1, R12 ; 除数
BL udiv_armv4t ; R0=项的绝对值,R1=余数
; 子步骤5:应用符号位
CMP R6, #1
BEQ term_pos ; 正号 → 直接保留
; 负号 → 取补码
MVN R0, R0
ADD R0, R0, #1
term_pos
; 子步骤6:有符号累加当前项
MOV R1, R0 ; R1=当前项
MOV R0, R5 ; R0=累加和
BL sadd ; 有符号加法
MOV R5, R0 ; 更新累加和
; 子步骤7:更新参数
CMP R6, #1
BEQ set_neg
MOV R6, #1 ; 当前为-1 → 转为1
B sign_updated
set_neg
MVN R6, #0 ; 1 → -1
sign_updated
ADD R7, R7, #2 ; 指数+2
ADD R8, R8, #1 ; 项数+1
CMP R8, #MAX_TERMS ; 是否达到4项
BLT sin_loop ; 继续循环
; 步骤3:结果范围检查
MOV R0, R5
CMP R0, #-1000
BLT sin_overflow
CMP R0, #1000
BGT sin_overflow
B sin_store
sin_overflow
; 溢出处理
LDR R2, =overflow_flag
MOV R1, #1
STR R1, [R2]
MOV R0, #0
sin_store
LDMFD SP!, {R4-R12, LR} ; 恢复寄存器
B store_result
; -------------------------- 多步运算 --------------------------
call_multi
LDR R0, =a_multi
LDR R0, [R0]
LDR R1, =b_multi
LDR R1, [R1]
ADD R2, R0, R1 ; a + b
LDR R0, =c_multi
LDR R0, [R0]
UMULL R3, R4, R2, R0 ; (a + b) * c
MOV R2, R3 ; 更新结果
LDR R0, =d_multi
LDR R0, [R0]
SUB R0, R2, R0 ; (a + b) * c - d
B store_result
; -------------------------- 溢出处理 --------------------------
set_overflow
LDR R2, =overflow_flag
MOV R1, #1
STR R1, [R2]
B store_result
; -------------------------- 存储结果 --------------------------
store_result
LDR R2, =result
STR R0, [R2]
B main
END 这个代码在keil软件上调试的时候应该怎么调试
最新发布