"auipc dest, label" (and "la dest,label") don't produce expected listing

1

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!

assembly
riscv
asked on Stack Overflow Apr 3, 2019 by K.A.

1 Answer

1

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

answered on Stack Overflow Apr 5, 2019 by TheThirdOne

User contributions licensed under CC BY-SA 3.0