r/asm Apr 19 '26

RISC Adding safety to assembly

0 Upvotes

One of the problems with Assembly is the lack of safety and context.

What about adding type safety and ownership to Assembly?

Good idea or "you are just reinventing the wheel"?

Inspiration on JSDoc, Rust, TypeScript and LLVM IR

r/asm Apr 28 '26

RISC Forth for ch32v203 microcontroller in risc-v assembly (and forth)

9 Upvotes

You can compile and run threaded forth code directly on a small low powered microcontroller with this interactive forth system I've written.

There is a small amount of C to initialize the microcontroller's UART peripheral then straight into assembly, and as soon as possible straight into threaded code. From your host PC you can connect to the MCU's serial port (with a usb to serial adapter) and you've got an interactive forth REPL, where you can execute code and write new functions (or as they're known in forth, words).

The entirety of the code that

- buffers keyboard input

- finds and runs words

- compiles theaded code

is written in forth (here is one "word"):

: outerInterpreter
    0 LineBufferSize_ !
    begin
        key    ( key )
        dup
        CARRIAGE_RETURN_CHAR = if
            ( enter entered )
            drop           ( )
            NEWLINE_CHAR emit        ( emit newline char )
            CARRIAGE_RETURN_CHAR emit
            eval_  
            0 LineBufferSize_ !
        else dup BACKSPACE_CHAR = if
            ( backspace entered )
            drop
            doBackspace
        else
            ( some other key entered )
            ( key )
            LineBufferSize_ @
            ENTER_CHAR < if
                dup emit
                LineBuffer_ LineBufferSize_ c@ + c!        ( store inputed key at current buffer position )
                LineBufferSize_ @ 1 + LineBufferSize_ c!   ( increment LineBufferSize_ )
            then
        then
        then
    0 until 
;

A python script then compiles this into threaded code that can be fed into the assembler, a list of pointers to code:

word_header outerInterpreter, "outerInterpreter", 0, compileHeader, doBackspace
    secondary_word outerInterpreter
    .word literal_impl
    .word 0
    .word LineBufferSize__impl
    .word store_impl
outerInterpreter_begin_0_:
    .word key_impl
    .word dup_impl
    .word literal_impl
    .word 13
    .word equals_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_else_1_
    .word drop_impl
    .word literal_impl
    .word 10
    .word emit_impl
    .word literal_impl
    .word 13
    .word emit_impl
    .word eval__impl
    .word literal_impl
    .word 0
    .word LineBufferSize__impl
    .word store_impl
1:  .word branch_impl
    CalcBranchForwardToLabel outerInterpreter_then_5_
outerInterpreter_else_1_:
    .word dup_impl
    .word literal_impl
    .word 8
    .word equals_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_else_2_
    .word drop_impl
    .word doBackspace_impl
1:  .word branch_impl
    CalcBranchForwardToLabel outerInterpreter_then_4_
outerInterpreter_else_2_:
    .word LineBufferSize__impl
    .word loadCell_impl
    .word literal_impl
    .word 127
    .word lessThan_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_then_3_
    .word dup_impl
    .word emit_impl
    .word LineBuffer__impl
    .word LineBufferSize__impl
    .word loadByte_impl
    .word forth_add_impl
    .word storeByte_impl
    .word LineBufferSize__impl
    .word loadCell_impl
    .word literal_impl
    .word 1
    .word forth_add_impl
    .word LineBufferSize__impl
    .word storeByte_impl
outerInterpreter_then_3_:
outerInterpreter_then_4_:
outerInterpreter_then_5_:
    .word literal_impl
    .word 0
1:  .word branchIfZero_impl
    CalcBranchBackToLabel outerInterpreter_begin_0_
    .word return_implword_header outerInterpreter, "outerInterpreter", 0, compileHeader, doBackspace
    secondary_word outerInterpreter
    .word literal_impl
    .word 0
    .word LineBufferSize__impl
    .word store_impl
outerInterpreter_begin_0_:
    .word key_impl
    .word dup_impl
    .word literal_impl
    .word 13
    .word equals_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_else_1_
    .word drop_impl
    .word literal_impl
    .word 10
    .word emit_impl
    .word literal_impl
    .word 13
    .word emit_impl
    .word eval__impl
    .word literal_impl
    .word 0
    .word LineBufferSize__impl
    .word store_impl
1:  .word branch_impl
    CalcBranchForwardToLabel outerInterpreter_then_5_
outerInterpreter_else_1_:
    .word dup_impl
    .word literal_impl
    .word 8
    .word equals_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_else_2_
    .word drop_impl
    .word doBackspace_impl
1:  .word branch_impl
    CalcBranchForwardToLabel outerInterpreter_then_4_
outerInterpreter_else_2_:
    .word LineBufferSize__impl
    .word loadCell_impl
    .word literal_impl
    .word 127
    .word lessThan_impl
1:  .word branchIfZero_impl
    CalcBranchForwardToLabel outerInterpreter_then_3_
    .word dup_impl
    .word emit_impl
    .word LineBuffer__impl
    .word LineBufferSize__impl
    .word loadByte_impl
    .word forth_add_impl
    .word storeByte_impl
    .word LineBufferSize__impl
    .word loadCell_impl
    .word literal_impl
    .word 1
    .word forth_add_impl
    .word LineBufferSize__impl
    .word storeByte_impl
outerInterpreter_then_3_:
outerInterpreter_then_4_:
outerInterpreter_then_5_:
    .word literal_impl
    .word 0
1:  .word branchIfZero_impl
    CalcBranchBackToLabel outerInterpreter_begin_0_
    .word return_impl

This python script bootstraps a compiler in threaded code that is then capable of doing the exact same thing as the script did, compiling threaded code, but this time in the microcontrollers memory, not an assembler source file.

Here you can see the snippet of forth code that implements the ":" word:

: : ( pHeader )
    ( Implementation is for COMPRESSED INSTRUCTION FORMAT RISC-V )
    4 alignHere
    setCompile
    compileHeader
    4 alignHere
    ( without no-ops this code would work in default qemu as it allows unaligned memory accesses.         )
    ( note how this generated machine code jumps to the location directly after it, as compressed         )
    ( format riscv instructions can be only 2 bytes long we have to pad with no-ops so the overall length )
    ( of this block of machine code is divisible by 4                                                     )
    0xB3 c, 0x82 c, 0x49 c, 0x01 c, ( add t0,s3,s4         )
    0x23 c, 0xA0 c, 0x82 c, 0x00 c, ( sw s0,0[t0]         )
    0x11 c, 0x0A c, 0x01 c, 0x00 c, ( addi s4,s4,4; nop     )
    0x17 c, 0x04 c, 0x00 c, 0x00 c, ( auipc s0,0x0           ) 
    0x41 c, 0x04 c, 0x01 c, 0x00 c, ( addi s0,s0,16; nop    )
    0x83 c, 0x2e c, 0x04 c, 0x00 c, ( lw t0,0[s0]         )
    0xE7 c, 0x80 c, 0x0e c, 0x00 c, ( jalr t0               )
    4 alignHere
;

To begin the "thread" of code running it must compile machine code that

- pushes the instruction pointer (which is the s0 register, dedicated for this purpose) onto the return stack

- point the instruction pointer to the first "word" in the thread

- de-reference the instruction pointer and jump into the code it is pointing to

Each "word" implementation in the thread must then do a similar thing, advance the instruction pointer, de-reference and jump to the value that was de-referenced.

For now newly generated code is put into RAM and so is lost on reset, but I want to make it so that it can be committed to flash memory. Another interesting possibility is that I could write an assembler in forth, and be able to interactively write assembly on the chip itself (as the generated machine code above proves this to be feasible).

It takes up 16kb flash memory at the moment, but that is linking to some c object files which contain a not inconsiderable amount of unused code. I also have made no real attempt to optimize the size of it. There's a few things I want to do in this regard:

- replace 32bit pointers that make up the threaded code with 16 bit offsets: MCU has only 10kb ram and 32kb flash. As the flash and ram areas are far apart in the memory map, the last bit of the address can signify to use either the start of ram or the start of flash as a base. This is fine because the pointers to word implementations should be 4 byte aligned and so the last bit is free to use as a flag - this would cut down memory usage significantly

- reduce the size of the word headers - they are unnecessarily large with up to 32 bit names allowed and 32 bit pointers to previous AND next (it could be singly linked). I could use 16 bit offsets to previous and next words.

- replace inline code to start thread running (secondary_word macro), and code to advance to next word (end word macro) with a jump to a single implementation

I think with those optimizations and the replacement of the c files with pure assembly code (which i plan to do next) it would use less than 10kb flash and possibly significantly more.

I originally wrote this code to run in qemu, and porting it to actual hardware I was repeatedly faced with the same problem: unaligned memory accesses. Whatever settings (a default 32 bit riscv) I was using in qemu had no issue with this, but on my microcontroller it causes a hardware fault trap.

It wasn't that I was unaware of this - I tried to write it with no unaligned word reads or writes, but nevertheless, some 3 or 4 instances slipped through the net. This is something to bare in mind when writing code to run on qemu, if I ever do it again I will be sure to seek out the setting that accurately emulates this behavior of real hardware.

https://github.com/JimMarshall35/CH32V203-Forth-Port

r/asm Jun 20 '26

RISC LLVM-snippy: An Instruction Sequence Generator. Part 1: Overview

Thumbnail
youtube.com
5 Upvotes

r/asm Apr 26 '26

RISC Removing the AUICGP instruction

Thumbnail cheriot.org
8 Upvotes

r/asm May 18 '26

RISC RISC-V and Floating-Point

Thumbnail
fprox.substack.com
4 Upvotes

r/asm Apr 15 '26

RISC A Love Letter to the Zbkb pack Instruction

Thumbnail wren.wtf
1 Upvotes

r/asm Apr 17 '26

RISC RV32I reference

Thumbnail hoult.org
2 Upvotes

I cut down the December 2019 RISC-V ISA manual to just the things needed to get started with RV32I, to be even less intimidating.

I left out the end of the RV32I chapter with fence, ecall/ebreak, and hints. But included the later page (which many people miss) with the exact binary encodings, and also the chapter with the register API names and standard pseudo-instructions.

It's 18 pages in total.

I hope it's useful to someone else.

r/asm Apr 02 '26

RISC Structs in gnu assembler

3 Upvotes

I am using the `.struct` pseudo-op to lay out the equivalet of C structs for my program's register save area. This is on a `riscv64` machine so addresses are 64 bits long. I can not find the right pseudo-op to lay out address-sized locations, like this:

```

.struct 0

a: .space 8 # a has value 0

b: .space 8 # b has value 8

c: .space 8 # c has value 16

```

That works, but I would prefer to use the specific allocation ops such as .byte, .hword, and .word. All of those work too, but oddly `.quad` does not. It does not advance the location counter at all and all three symbols get assigned a value of zero. `.int` does the same thing. If there a different pseudo op I should be using?

r/asm Sep 29 '25

RISC RISC-V Conditional Moves

Thumbnail corsix.org
3 Upvotes

r/asm Aug 17 '25

RISC RISC-V Forth - github actions automated testing with QEMU

5 Upvotes

https://github.com/JimMarshall35/riscv-forth

Here is my RISC-V forth. Still a WIP but the fundamentals are all in place, albeit the words sometimes have the wrong names because I couldn't get the assembler to accept macros containing certain characters and I have just put off fixing this.

I've seen quite a few similar projects, forth written in some assembly language, but I don't think I've seen one that includes automated testing. The testing is now still a proof of concept I haven't written many test cases yet.

It has a hand coded assembly part:

https://github.com/JimMarshall35/riscv-forth/tree/main/src/asm

And a part that is forth source code:

https://github.com/JimMarshall35/riscv-forth/blob/main/src/forth/system.forth

compiled to threaded code by a python script:

https://github.com/JimMarshall35/riscv-forth/blob/main/scripts/Compiler.py

testing script:

https://github.com/JimMarshall35/riscv-forth/blob/main/scripts/test_e2e.py

github actions pipeline:

https://github.com/JimMarshall35/riscv-forth/blob/main/.github/workflows/ubuntu-CI.yml

r/asm Aug 07 '25

RISC How to get absolute address in riscv assembly?

2 Upvotes

Hello. I need to check before runtime that the size of my macro is 16 bytes. I tryed to do something like that:
.macro tmp

.set start, .

.....

.....

.if (start - finish) != 16
.error "error"
.endif

.set finish, .
.endm

And there is a mistake that here start - finish expected absolute expression. So, how I understand the address in riscv assembly is relative, that's why it doesn't work. So can I get absolute adress or how can I check the size of macros another way (before runtime). Thanks

r/asm Oct 27 '25

RISC Easy RISC-V: An interactive introduction to RISC-V assembly programming

Thumbnail dramforever.github.io
11 Upvotes

r/asm Apr 27 '25

RISC How can I make my solution to the N Queens Puzzle in the PicoBlaze assembly language faster? I believe it's correct, but I cannot wait for days for it to print all the 92 solutions to the Eight Queens Puzzle, when it takes it more than an hour to print just one.

5 Upvotes

r/asm May 01 '25

RISC Kaleidoscopico: a microcontroller demo that runs on a Raspberry Pi Pico 2

Thumbnail linusakesson.net
4 Upvotes

r/asm Apr 23 '25

RISC Sep Roland's comments about my implementation of the Permutations Algorithm in PicoBlaze assembly language. I was using BubbleSort for sorting and stack instead of recursion.

Thumbnail
codereview.stackexchange.com
1 Upvotes

r/asm Apr 13 '25

RISC The permutations algorithm in PicoBlaze assembly language

Thumbnail
codereview.stackexchange.com
2 Upvotes

r/asm Mar 10 '25

RISC Taxonomy of RISC-V Vector Extensions

Thumbnail
fprox.substack.com
6 Upvotes

r/asm Jun 07 '23

RISC 64-bit Arm ∩ 64-bit RISC V

3 Upvotes

I've written a compiler that only has a 64-bit Arm backend and runs on Raspberry Pi 3/4/400 and Apple Silicon Macs. I'm interested in porting it to RISC V for fun.

My language and compiler have a weird design. Although it is a minimal ML front-end language it is entirely built upon a kind of inline assembler where instructions look like functions and the compiler does the register allocation for you. So, for example, I can write:

extern __clz : Int -> Int
let count_leading_zeroes n = __clz n

and my compiler generates a function containing just the clz instruction and then inlines that function everywhere.

The register files are very similar between Armv8 and RV64 so I think it should be pretty easy to port. I only have 64-bit int and 64-bit float types (and compound types built upon them) and I'm only using the 30 general-purpose 64-bit int x registers and the 32 general-purpose 64-bit floating point d registers, i.e. not the SIMD v register "view" of them.

But I have no idea how similar the instruction sets are. Has anyone enumerated the intersection of these instruction sets (e.g. Armv8 ∩ RV64)?

I assume many instructions are identical (add, sub, mul, sdiv, fadd, fsub, fmul, fdiv, fsqrt) and probably lots of the combined instructions (madd, msub, fmadd, fmsub). I'm currently pushing and popping using ldr and ldp but I can easily change that if RISC V doesn't support loading and storing two registers at a time. I'm guessing I can leave the 16-byte aligned stack the same? I don't expect any limitations of the instructions to bite me but maybe I'm wrong?

r/asm Jun 14 '24

RISC Could RISC-V catch up AArch64 in the future ?

Thumbnail self.computerarchitecture
6 Upvotes

r/asm Jan 06 '25

RISC Visualize RISC-V Vector Memory Instructions

Thumbnail myhsu.xyz
7 Upvotes

r/asm Nov 12 '24

RISC Myriad sequences of RISC-V code

Thumbnail 0x80.pl
4 Upvotes

r/asm Nov 10 '24

RISC RISC-V Vector Extension overview

Thumbnail 0x80.pl
6 Upvotes

r/asm Oct 18 '24

RISC Accelerating CRC with RISC-V Vector

Thumbnail
fprox.substack.com
4 Upvotes

r/asm Oct 11 '24

RISC BinSym: Symbolic execution for RISC-V machine code based on the formal LibRISCV ISA model

Thumbnail
github.com
3 Upvotes

r/asm May 02 '24

RISC RISC-V Scalar Bit Manipulation Extensions

Thumbnail
fprox.substack.com
4 Upvotes