risc-v中文社区

 找回密码
 立即注册
查看: 1643|回复: 1

Error: internal_relocation (type: OFFSET_IMM) not fixed up

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2022-10-10 09:30:34 | 显示全部楼层 |阅读模式
.global _start
_start:
        mov r1,#0x10
        mov r2,#0x20
        ldmia r1,{r2} //将r1对应的内存地址中的数据送给r2寄存器
        //ldmia r1,[r2] Error: expression too complex -- `ldmia r1,[r2]'
        //ldmia r1,{[r2]} Error: ARM register expected -- `ldmia r1,{[r2]}'
        //总结:ldm和ldr指令从CPU角度来看都是加载,即从存储器中将数据传到寄存器中,不过ldr指令中的目的寄存器在左边,而ldm指令中目的寄存器列表在右边
        //ldr/ldrb/ldrh 目的寄存器 源存储器对应的地址    而ldm指令则是  ldm 源存储器对应的首地址 目的寄存器列表
        //总之,ldm和ldr等加载类的指令都是从内存中将数据送到寄存器
        
        //str/strb/strh/stm等指令中的st是store的简写即从CPU角度来看是保存,也就是从CPU内部的寄存器将数据送到存储器中
        //str/strb/strh 源寄存器,目的存储器对应地址  而stmfd(是满递减堆栈类型)目的存储器对应地址首地址 源寄存器
        
        //再次总结:
        //加载时,ldr/ldrb/ldrh将数据从存储器加送到寄存器等一次性加载类指令的源存储器对应的地下写在右边,ldm多次加载指令的源存储器对应的首地址写在左边
        //保存时,str/strb/strh将数据从寄存器送到存储器等一次性保存类指令的源寄存器写在左边,stm多次保存类指令对应的源寄存器写在右边
        
        //单次加载和多次加载的源存储器地址或首地址方向相反
        //单次保存和多次保存的源寄存器方向相反
        //加载和保存不论是单次还是多次在方向上来说最好不要记混了,最多只需要记住:加载时的源与保存时的源方向相反
        
        //LDR指令有多种寻址方式,见t.s
        //STR指令应该也有多种寻址方式
        //a)可以寄存器寻址吗?
        //STR R0,R1  //出现:Error: internal_relocation (type: OFFSET_IMM) not fixed up  https://blog.csdn.net/szm1234/article/details/109764869
        //出现上面的internal_relocation错误,分析见https://blog.csdn.net/jn_statham/article/details/106823270所以需要先初始化内存之后再执行上句。
        
        //b)可以立即数寻址吗?
        //STR R0,#0x1000  //出现:Error: internal_relocation (type: OFFSET_IMM) not fixed up https://blog.csdn.net/szm1234/article/details/109764869
        STR R0,#0x10 //也是出现:Error: internal_relocation (type: OFFSET_IMM) not fixed up
        //c)可以寄存器移位寻址吗?
        //STR R0,R1,LSL #3  Error: garbage following instruction -- `str R0,R1,LSL#3'
        //STR R0,[R1],R2,LSL #4 Error: garbage following instruction -- `str R0,[R1],R2,LSL#4'
        LDR R0,[R1,R2,LSL #2] //这句编译成功
        //LDR R0,[R1],R2,LSL #2 //这句出现:Error: garbage following instruction -- `ldr R0,[R1],R2,LSL#2'
        //d)可以寄存器间接寻址吗?
        //STR R0,[R2]  
        //e)可以基址变址寻址吗?
        STR R1,[R2,#4]
        STR R1,[R2,R3]
        
        b .
.end

回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2022-10-10 10:53:11 | 显示全部楼层
        //MOV R0,#0x10
        //MOV R1,#0x20
        //STR R0,R1  还是出现:internal_relocation
        //LDR R0,= #0x10
        //LDR R1,= #0x20
        //STR R0,R1 还是出现:internal_relocation
        //LDR R0,= 0x10
        //LDR R1,= 0x20
        //STR R0,[R1]  //当改为STR R0,[R1]就正常了
        //MOV R0,#0x10
        //MOV R1,#0x20
        //STR R0,[R1] 重新将最初的代码如此处修改之后也正常了

        //LDR R0,0x10 出现 Error:internal_relocation
        //LDR R1,0x20 出现 Error:internal_relocation
        //STR R0,[R1]
        //LDR R0,#0x10 出现 Error:internal_relocation
        //LDR R1,#0x20 出现 Error:internal_relocation
        //STR R0,[R1]
        //根据https://blog.csdn.net/new_eggs/article/details/8468008中所说的,从内存中将数据加载到寄存器LDR指令(注意:不是LDR伪指令),LDR R0,0x12345678
        //表示将内存中地址为0x12345678的内容传给R0
        //LDR R0,0x12345678 结果还是出现:Error: internal_relocation (type: OFFSET_IMM) not fixed up
        //关于LDR指令的二种用法可参考:https://blog.csdn.net/lsm424/article/details/50447912
        //比如:
        //ldr pc,=label 将label后的数据或指令的运行地址赋值给PC,运行地址=链接地址+label相对程序起始地址的偏移
        //ldr pc,label 将label后的数据或指令内容赋值给PC
        //但如果不是label而是立即数呢???立即数前面必须要有=,只有立即数前面有=,
        //LDR指令才会将立即数装入寄存器中(汇编器将此LDR伪指令变为MOV指令),
        //且当立即数比较大时(超过8位长度),汇编器将生成一个文字池,最后生成LDR R1,[PC,#OFFSET]
        //如果立即数前面没有=,那么指令的作用其实本意是想将这个立即数对应的内存地址中的值
        //加载给寄存器,但汇编器汇编之后还需要链接,无法定位内存地址,所以将会提示:Error: internal_relocation
        //所以LDR R0,0x12345678和LDR R0,0x10都会出现Error: internal_relocation
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-4-26 03:05 , Processed in 0.023866 second(s), 26 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表