I'm trying to write an assembler code for RISC-V (first time for RISC-V although I wrote for few other CPUs) and what I see in the listing doesn't looks like what I expected: I'm attempting to use "la dest,label" to load the address of a label into a register which'll later be used as a pointer. However, in the listing I see the values of PC-relative offsets as zeros. When I insert a "j label" instruction just to test the assembler I see the instruction offset fields of the correct values. As if the "auipc" instruction doesn't work correctly (or I make some beginners mistake).
I'm using the assembler of "binutils-2.28" compiled for the target of "riscv32".
Here's the assembler code:
.section .text
.globl _start
_start:
.equ MON_OUT_ADDR, 0x00000000 # TBD
.equ MON_BASE_ADDR, 0x12345678 # TBD
.equ MON_OUT_ADDR_OFFSET, 0x0
.equ BASE_ADDR_OFFSET, 0x4
#.org 0x0 # TBD.
mon_isr:
j isr_data # <=== Dummy instruction, just to test riscv32-as
la x1,isr_data # x1 - ISR data ptr.
la x1,wfi_endless_loop # <=== Dummy instruction, just to test riscv32-as
lui x1,%hi(isr_data) # <=== Dummy instruction, just to test riscv32-as
auipc x1,%pcrel_hi(isr_data) # <=== Dummy instruction, just to test riscv32-as
addi x1,x1,%lo(isr_data) # <=== Dummy instruction, just to test riscv32-as
auipc x1,%hi(0x00010004) # <=== Dummy instruction, just to test riscv32-as
addi x1,x1,%lo(0x00010004) # <=== Dummy instruction, just to test riscv32-as
lw x15,MON_OUT_ADDR_OFFSET(x1)
lw x8,BASE_ADDR_OFFSET(x1)
wfi_endless_loop:
j wfi_endless_loop
.org 0x00010000
#isr_data:
.word MON_OUT_ADDR
isr_data:
.word MON_BASE_ADDR
And here's the listing:
GAS LISTING /some_path/temp/riscv_asm/debug.asm page 1
1 .section .text
2 .globl _start
3 _start:
4
5
6 .equ MON_OUT_ADDR, 0x00000000 # TBD
7 .equ MON_BASE_ADDR, 0x12345678 # TBD
8
9 .equ MON_OUT_ADDR_OFFSET, 0x0
10 .equ BASE_ADDR_OFFSET, 0x4
11
12
13
14 #.org 0x0 # TBD.
15 mon_isr:
16
17 0000 6F004100 j isr_data # <=== Dummy instruction, just to test riscv32-as
18 0004 97000000 la x1,isr_data # x1 - ISR data ptr.
18 93800000
19
20 000c 97000000 la x1,wfi_endless_loop # <=== Dummy instruction, just to test riscv32-as
20 93800000
21 0014 B7000000 lui x1,%hi(isr_data) # <=== Dummy instruction, just to test riscv32-as
22 0018 97000000 auipc x1,%pcrel_hi(isr_data) # <=== Dummy instruction, just to test riscv32-as
23 001c 93800000 addi x1,x1,%lo(isr_data) # <=== Dummy instruction, just to test riscv32-as
24 0020 97000100 auipc x1,%hi(0x00010004) # <=== Dummy instruction, just to test riscv32-as
25 0024 93804000 addi x1,x1,%lo(0x00010004) # <=== Dummy instruction, just to test riscv32-as
26
27 0028 83A70000 lw x15,MON_OUT_ADDR_OFFSET(x1)
28 002c 03A44000 lw x8,BASE_ADDR_OFFSET(x1)
29
30 wfi_endless_loop:
31 0030 6F000000 j wfi_endless_loop
32
33
34
35
36
37 0034 00000000 .org 0x00010000
37 00000000
37 00000000
37 00000000
37 00000000
38
39
40 #isr_data:
41 10000 00000000 .word MON_OUT_ADDR
42
43 isr_data:
44 10004 78563412 .word MON_BASE_ADDR
45
46
GAS LISTING /some_path/temp/riscv_asm/debug.asm page 2
DEFINED SYMBOLS
/some_path/temp/riscv_asm/debug.asm:3 .text:0000000000000000 _start
/some_path/temp/riscv_asm/debug.asm:6 *ABS*:0000000000000000 MON_OUT_ADDR
/some_path/temp/riscv_asm/debug.asm:7 *ABS*:0000000012345678 MON_BASE_ADDR
/some_path/temp/riscv_asm/debug.asm:9 *ABS*:0000000000000000 MON_OUT_ADDR_OFFSET
/some_path/temp/riscv_asm/debug.asm:10 *ABS*:0000000000000004 BASE_ADDR_OFFSET
/some_path/temp/riscv_asm/debug.asm:15 .text:0000000000000000 mon_isr
/some_path/temp/riscv_asm/debug.asm:43 .text:0000000000010004 isr_data
/some_path/temp/riscv_asm/debug.asm:30 .text:0000000000000030 wfi_endless_loop
/some_path/temp/riscv_asm/debug.asm:18 .text:0000000000000004 .L0
/some_path/temp/riscv_asm/debug.asm:20 .text:000000000000000c .L0
NO UNDEFINED SYMBOLS
The offset in instructions like "la x1,isr_data" looks like zero while it should be difference between the address of that label (0x10004) and the address of the next instruction, IIRC. Is there a bug in the assembler or am I doing something wrong?
TIA!
I suspect the reason why the immediate fields are 0 is because you are looking at an object file which hasn't been linked.
if you run readelf
on your executable with -r
which shows relocation information you should see something like:
Relocation section '.rela.text' at offset 0x1018c contains 11 entries:
Offset Info Type Sym.Value Sym. Name + Addend
00000004 00000917 R_RISCV_PCREL_HI2 00010004 isr_data + 0
00000008 00000b18 R_RISCV_PCREL_LO1 00000004 .L0 + 0
0000000c 00000a17 R_RISCV_PCREL_HI2 00000030 wfi_endless_loop + 0
00000010 00000c18 R_RISCV_PCREL_LO1 0000000c .L0 + 0
00000014 0000091a R_RISCV_HI20 00010004 isr_data + 0
00000014 00000033 R_RISCV_RELAX 0
00000018 00000917 R_RISCV_PCREL_HI2 00010004 isr_data + 0
0000001c 0000091b R_RISCV_LO12_I 00010004 isr_data + 0
0000001c 00000033 R_RISCV_RELAX 0
00000000 00000911 R_RISCV_JAL 00010004 isr_data + 0
00000030 00000a11 R_RISCV_JAL 00000030 wfi_endless_loop + 0
This is the information the linker will use to replace the values in the instructions with their proper values and make the program executable. So the reason the immediates are always 0 is because they haven't been given a final value yet.
You can make the object file executable by running riscv-ld yourobject.o -o yourexecutable
User contributions licensed under CC BY-SA 3.0