cassemblyrom

Specify the memory address where a single instruction in c will be assembled


I built a SoC written in Verilog, compiled the c code into a binary file and initialized the SoC ROM with it. In order to design an error injection, I needed to be able to artificially specify the ROM address after the assembly of an instruction such as printf ("123"). Is there a way to do this, for example, using inline assembly?


Solution

  • There might be a very hacky and unreliable way that happens to work in a debug build, relying on assumptions about how compilers work. IDK why you'd want to do it; you can't jump there from outside the function. If you just want to be able to set a breakpoint, normally you can do that by line number with debug info.


    Creating an asm label / symbol-table entry

    printf("123") can't compile to a single instruction. There will be some that set up a pointer arg, and one or more that actually do a call printf or equivalent. In a debug build those will be contiguous block, otherwise they might not be.

    In a debug build (optimization disabled), if you use inline asm to emit a label in the middle of your C function, like asm(".globl foo; foo:" ::: "memory"), it will probably be right before the block of instructions corresponding to the next C statement. (In an optimized build, the instructions corresponding to one C statement won't be in a contiguous block, and there'd be no way to do anything like what you're asking, except maybe with C goto labels like foo: and using GNU C labels-as-values to take their address. But I don't think you could control their address with the linker since you wouldn't know an asm symbol name.)


    Using a linker script to move the start of a section so your symbol lands at the desired address

    You can use a linker script to place the start of the .text section at a certain address. Something like . = 0x401000 before emitting the segment that maps the sections you want.

    If you compute that address like . = 0x401000 - (symbol - start_of_text), using the distance of the symbol from the start of the section, then the symbol should end up at the address you want.

    You can put individual functions in their own section so you can play with layout in the linker (gcc -ffunction-sections) so you could do that on a per-function basis.


    I wouldn't recommend doing this. If something you're designing relies on this to work correctly, design it differently. This is horrible.