LC3访问违例:xFE00与x3200差异及代码适配方案咨询
LC3程序访问违例问题:xFE00解析、报错原因及修复方案
1. xFE00到底是什么?
在LC3的内存布局里,xFE00是系统栈的初始栈顶地址。LC3内存分为用户可自由使用的空间(x0000xDFFF)和操作系统专属的系统空间(xE000xFFFF),xFE00属于后者,是系统用来管理栈帧、保存上下文的核心区域,用户程序无权限直接访问执行。
2. 为什么会触发访问违例?
你的主程序里有个致命错误:
LD R6, top_stack_addr ; 把系统栈顶地址加载到R6 JSRR R6 ; 直接跳转到R6指向的地址执行
JSRR R6会让程序跳到xFE00去执行代码,但这里是受保护的系统区域,既没有你写的子程序逻辑,用户程序也没权限访问,自然就触发访问违例了。
你改成x3200能正常运行,完全是因为x3200是你编写的SUB_GET_STRING_3200子程序的起始地址,跳转到这里才是正确的执行入口。
3. 不修改xFE00的修复方法
作业要求保留top_stack_addr .FILL xFE00,说明这条指令是用来初始化栈指针的(LC3规范里用R6做栈指针),不是让你用来调用子程序的!你要做的就是把错误的调用指令改成正确的:
修正后的主程序代码
.orig x3000 ; 初始化栈指针(保留原指令不动) LD R6, top_stack_addr ; 请勿修改,除备份/恢复外请勿使用R6 LEA R1,CHAR_ARRAY ; 把错误的JSRR R6换成正确的子程序调用 JSR SUB_GET_STRING_3200 LEA R0,CHAR_ARRAY HALT ; 本地数据 top_stack_addr .FILL xFE00 ; 保持原样 CHAR_ARRAY .BLKW #100 .end
额外的规范优化(建议执行)
你的子程序里定义了BACKUP_R5_3200,但开头没备份R5、结尾也没恢复。R5是你用来存储返回值的寄存器,为了不破坏主程序里R5的原有数据,得补上这两步:
子程序开头新增备份R5:
SUB_GET_STRING_3200 ST R0, BACKUP_R0_3200 ST R1, BACKUP_R1_3200 ST R2, BACKUP_R2_3200 ST R3, BACKUP_R3_3200 ST R4, BACKUP_R4_3200 ST R5, BACKUP_R5_3200 ; 补上备份R5 ST R6, BACKUP_R6_3200 ST R7, BACKUP_R7_3200
子程序结尾新增恢复R5:
LD R0, BACKUP_R0_3200 LD R1, BACKUP_R1_3200 LD R2, BACKUP_R2_3200 LD R3, BACKUP_R3_3200 LD R4, BACKUP_R4_3200 LD R5, BACKUP_R5_3200 ; 补上恢复R5 LD R6, BACKUP_R6_3200 LD R7, BACKUP_R7_3200 RET
内容的提问来源于stack exchange,提问作者henrypham
相关产品推荐
相关产品推荐

