(MIPS 24KEc) MT7688 (LinkIt Smart 7688 Duo)
Branch、Jump指令的差異
參考資訊:
1. MIPS_Vol2
2. jump-instruction-in-mips-assembly
main.s
.extern _start .set noreorder .section .init _start: b reset .text reset: li $8, 0xb0000604 li $9, (1 << (44 - 32)) sw $9, 0($8) loop: li $8, 0xb0000624 xori $9, $9, (1 << (44 -32)) sw $9, 0($8) li $8, 5000 0: addi $8, -1 bnez $8, 0b nop j loop nop
上面這段程式,看起來並沒有問題,只是將$9的第12位元做XOR運算,然後輸出設定LED,但是,實際上是無法正確執行,LED無法閃爍
Linker Script
OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") OUTPUT_ARCH(mips) ENTRY(_start) SECTIONS { ENTRY(_start) . = 0x0000; .init : { *(.init) } . = 0x0400; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } }
使用IDA Pro查看時,因為記憶體載入使用預設0x00000000,因此,看不出問題
改成MT7688預設的執行位址(從SPI執行)0xBC000000,就可以知道為何程式無法正常執行,因為它跳轉到0xB0000410
J(Jump)指令使用的絕對位址,因此,當Linker Script是從0x0400開始時,編譯後,被計算出來的位址就會是錯的
解法:
1. 修改Linker Script的記憶體位址
2. 改成B(Branch)指令,因為Branch指令是使用相對位址方式計算
3. 在執行Jump指令時,加上偏移位址