4

In this assembly file below, the macro jump_table should automagically create ... a jump table to consecutively numbered labels like jump_0, jump_1, ... jump_<n>.

It seems there is no loop feature in as .macro directive and the official documentation seems to suggest what appears to be a recursive macro.

Anyway, this is the file:

.section .text
.align 4

.macro jump_table name init last
  j \name\()_\init
  .if \last > \init
  jump_table \name \init+1 \last
  .endif
.endm

jump_table jump 0 3

jump_0:
  nop
jump_1:
  nop
  nop
jump_2:
  nop
  nop
  nop
jump_3:
  nop
  nop
  nop
  nop

The resulting binary, once disassembled with objdump, yields this:

0000000000000000 <jump_0-0x1c>:
   0:   00000013            nop
   4:   00000013            nop
   8:   00000013            nop
   c:   0100006f            j   1c <jump_0>
  10:   00c0006f            j   1c <jump_0>
  14:   00a0006f            j   1e <jump_0+0x2>
  18:   0060006f            j   1e <jump_0+0x2>

000000000000001c <jump_0>:
  1c:   00000013            nop

0000000000000020 <jump_1>:
  20:   00000013            nop
  24:   00000013            nop

0000000000000028 <jump_2>:
  28:   00000013            nop
  2c:   00000013            nop
  30:   00000013            nop

0000000000000034 <jump_3>:
  34:   00000013            nop
  38:   00000013            nop
  3c:   00000013            nop
  40:   00000013            nop
  44:   00000013            nop
  48:   00000013            nop
  4c:   00000013            nop

The jump table looks weird to me: offsets are decreasing while I would expect them to increase. Moreover, labelling also looks weird.

If I understood correctly, I should expect something like:

  j   1c <jump_0>
  j   20 <jump_1>
  j   28 <jump_2>
  j   34 <jump_3>

I bet I am missing something and some explanation would help me greatly.

I am using riscv64-elf-as and riscv64-elf-objdump v2.44 on MacOS M4.

3
  • 2
    I think \init will not evaluate the actual number, but just the text with +1 appended, thus, you get j jump_0+1, j jump_0+1+1, etc (which the assembler then rounds to the next valid address, i.e., jump_0, jump_0, jump_0+2, jump_0+2, ... Commented May 14 at 9:11
  • 1
    Interesting... Do I need to use those "(...)" as per documentation? I was getting errors from as. It's not clear to me how those assembler directives evaluate stuff. Commented May 14 at 10:10
  • 1
    I don't know if that works directly. I know that the C/C++ preprocessor also will not simplify arithmetic expressions, probably that is is the same for as. Commented May 14 at 10:51

1 Answer 1

3

\init+1 will not be evaluated before it gets passed recursively, therefore your macro creates something like this:

j  jump_0
j  jump_0+1
j  jump_0+1+1
j  jump_0+1+1+1

Which the assembler appears to round to the next valid address, i.e., in your case:

j   1c <jump_0>
j   1c <jump_0>
j   1e <jump_0+0x2>
j   1e <jump_0+0x2>

If you enable .altmacro-mode, you can have expressions evaluated before they get passed as parameters, using %(expr):

.altmacro

.macro jump_table name init last
  j \name\()_\init
  .if \last > \init
  jump_table \name, %(\init+1), \last
  .endif
.endm

Godbolt-Demo: https://godbolt.org/z/hGjEG6TE1

Sign up to request clarification or add additional context in comments.

8 Comments

It doesn't work for me (as v2.44). Please see here: pastebin.com/L25DrKTz . I get 3 entries, should be 2. I get only jump_0. Hex assembler seems not to match symbolic assembly.
jump_table jump 0 2 should be 3 entries, shouldn't it? But I don't know if you need something else to make .altmacro work properly, or if MacOS has a weird version of as.
Nope. It should be 2 as the test is "\last > \init" so 0 and 1 alone. And it should be 3 in your example. Right? Then I have no idea on how as works in general and on MacOS in particular. I only can use v2.44 there.
@EnzoR: Works for me with clang -target riscv32 (on x86-64 Linux), producing the same results as chtz's Godbolt link. llvm-objdump -drwC shows the relocation entries in the .o, otherwise you just see placeholders. (IDK if that's helpful; I saw macOS and thought of clang, but then I realized you're using actual GNU binutils with the version number you specified as a cross-assembler since you're targeting RV32, not MachO64 AArch64 or x86-64.)
@EnzoR Why do you expect 2 entries when you create an entry outside the .if block already? Even in your original question you were expecting 4 entries for jump_table jump 0 3.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.