Skip to content
Juan Gonzalez-Gomez edited this page Jan 8, 2025 · 27 revisions

Log

2023-06-21

Para migrar el proyecto del RiscvForth a un Riscv Real tengo que implementar rutinas que sustituyan las llamadas al sistema del Rars... Especialmente las llamadas al sistema de lectura de cadenas e impresión en la consola

Para ello voy a investigar y estudiar la herramienta "Keyboard and display MMIO emultaor" que viene con el RARs

Ya tengo un programa simple para imprimir caracteres (01-transiter.s). Las funciones de la UART están en el fichero uart.s

Para ponerlo en marcha hay que arrancar la herramienta del Keyboard and dipslay MMIO emulator. Ensamblar el programa, pinchar RESET en el emulador (NO EN EL RARS) y ejecutar. En la consola del emulador se mosgtrara el mensaje HI

Listo! Ya tengo la función de impresión implementada! (02-print.s)

Funcion de lectura funcionando!! (03-key.s)

2024-11-13

Emulador de Risc-V

Con la idea de hacer un ensamblador en Forth, que genere directamente código máquina, necesito evaluar un emulador de RV32I que sea sencillo... Veo que hay muchas alternativas, pero tengo que encontrar una que me sirva

Esta es una opción:

Pero lo veo demasiado complejo... no tengo claro si acepta fichero .bin con código máquina crudo (ni elf ni leches)...

He creado con el rars este programa: addi.s:

  addi x1,x0,0xaa

Y he generado el fichero con el código máquina: addi.bin

Lo intento ejecutar con rv32emu, pero no lo consigo porque espera un elf:

obijuan@JANEL:~/Develop/rv32emu$ ./build/rv32emu addi.bin 
rv32emu: src/riscv.c:231: rv_create: Assertion `elf && elf_open(elf, (attr->data.user)->elf_program)' failed.
Aborted (core dumped)

Este emulador tiene buena pinta, pero no me vale para hacer cosas básicas

Este es otro emulador, pero me temo que pasa lo mismo. Sólo admite elfs... (aunque no estoy 100% seguro)

Este otro funciona en el navegador... y tiene MUY BUENA PINTA... pero no permite cargar un .bin!!! o al menos no lo he encontrado!

Siiii!!! Tiene una opción para cargar un fichero .bin en la memoria... y se puede desensamblar... Joder.. este emulador es muy muy muy bueno!! De momento es el que voy a usar!!!!

Es una putada porque NO es opensource... vaya mierda....

Este emulador es buenísimo, y corre linux. En su momento lo he probado...PERO me da la sensación de que hay que pasarle un ELF... Tengo que probarlo. Le he dado a compilar pero parece que se está bajando las fuentes del kernel y lo está compilando!!!

obijuan@JANEL:~/Develop/mini-rv32ima$ make testdlimage
make -C mini-rv32ima testdlimage
make[1]: Entering directory '/home/obijuan/Develop/mini-rv32ima/mini-rv32ima'
./mini-rv32ima -f DownloadedImage
[    0.000000] Linux version 6.1.14 (cnlohr@cnlohr-1520) (riscv32-buildroot-linux-uclibc-gcc.br_real (Buildroot 2023.02-145-gf6c5488ad2) 12.2.0, GNU ld (GNU Binutils) 2.38) #4 Sat Mar 25 09:20:08 EDT 2023
[    0.000000] Machine model: riscv-minimal-nommu,qemu
[    0.000000] earlycon: uart8250 at MMIO 0x10000000 (options '1000000')
[    0.000000] printk: bootconsole [uart8250] enabled
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000080000000-0x0000000083ffefff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080000000-0x0000000083ffefff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x0000000083ffefff]
[    0.000000] riscv: base ISA extensions aim
[    0.000000] riscv: ELF capabilities aim
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16255
[    0.000000] Kernel command line: earlycon=uart8250,mmio,0x10000000,1000000 console=ttyS0
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[...]
[    0.094783] printk: bootconsole [uart8250] disabled
[    0.094783] printk: bootconsole [uart8250] disabled
``m[    0.098349] Freeing unused kernel image (initmem) memory: 1464K
[    0.098442] This architecture does not have kernel memory protection.
[    0.098530] Run /init as init process

Welcome to Buildroot
buildroot login: root
Jan  1 00:00:03 login[28]: root login on 'console'
~ # ls
coremark     duktapetest  fizzbuzz.js  hello_linux
~ # halt
~ # ls: /etc/init.d/S??*: No such file or directory
umount: devtmpfs busy - remounted read-only
umount: can't unmount /: Invalid argument
The system is going down NOW!
Sent SIGTERM to all processes
~ # [   67.412651] reboot: System halted
POWEROFF@0x000000000b6293da
make[1]: Leaving directory '/home/obijuan/Develop/mini-rv32ima/mini-rv32ima'
obijuan@JANEL:~/Develop/mini-rv32ima$

Voy a probar con el baremetal...

obijuan@JANEL:~/Develop/mini-rv32ima$ make testbare
make -C baremetal
make[1]: Entering directory '/home/obijuan/Develop/mini-rv32ima/baremetal'
../buildroot/output/host/bin/riscv32-buildroot-linux-uclibc-gcc -o baremetal.elf baremetal.c baremetal.S -fno-stack-protector -static-libgcc -fdata-sections -ffunction-sections -g -Os -march=rv32ima_zicsr -mabi=ilp32 -static -T flatfile.lds -nostdlib -Wl,--gc-sections
/home/obijuan/Develop/mini-rv32ima/buildroot/output/host/riscv32-buildroot-linux-uclibc/bin/ld.real: warning: baremetal.elf has a LOAD segment with RWX permissions
../buildroot/output/host/bin/riscv32-buildroot-linux-uclibc-objcopy baremetal.elf -O binary baremetal.bin
../buildroot/output/host/bin/riscv32-buildroot-linux-uclibc-objdump -t baremetal.elf > baremetal.debug.txt
../buildroot/output/host/bin/riscv32-buildroot-linux-uclibc-objdump -S baremetal.elf >> baremetal.debug.txt
make[1]: Leaving directory '/home/obijuan/Develop/mini-rv32ima/baremetal'
make -C mini-rv32ima testbare
make[1]: Entering directory '/home/obijuan/Develop/mini-rv32ima/mini-rv32ima'
./mini-rv32ima -f ../baremetal/baremetal.bin

Hello world from RV32 land.
main is at: 8000004c
Assembly code: I'm an assembly function.
Processor effective speed: 399 Mcyc/s

POWEROFF@0x00000000006ad000
make[1]: Leaving directory '/home/obijuan/Develop/mini-rv32ima/mini-rv32ima'
obijuan@JANEL:~/Develop/mini-rv32ima$

Me he fijado en esta línea:

../buildroot/output/host/bin/riscv32-buildroot-linux-uclibc-objcopy baremetal.elf -O binary baremetal.bin

Parece que pasa el elf a binario... a ver si hay suerte... Voy a probar con mi addi.bin:

Siiii.... He modificado addi.s para tener 2 instrucciones:

  addi x1,x0,0xaa
  addi x2,x0,0xbb

Este es el resultado:

obijuan@JANEL:~/Develop/mini-rv32ima$ ./mini-rv32ima/mini-rv32ima -f addi.bin  -c 1 -s
PC: 80000000 [0x0aa00093] Z:00000000 ra:00000000 sp:00000000 gp:00000000 tp:00000000 t0:00000000 t1:00000000 t2:00000000 s0:00000000 s1:00000000 a0:00000000 a1:83fff940 a2:00000000 a3:00000000 a4:00000000 a5:00000000 a6:00000000 a7:00000000 s2:00000000 s3:00000000 s4:00000000 s5:00000000 s6:00000000 s7:00000000 s8:00000000 s9:00000000 s10:00000000 s11:00000000 t3:00000000 t4:00000000 t5:00000000 t6:00000000
PC: 80000004 [0x0bb00113] Z:00000000 ra:000000aa sp:00000000 gp:00000000 tp:00000000 t0:00000000 t1:00000000 t2:00000000 s0:00000000 s1:00000000 a0:00000000 a1:83fff940 a2:00000000 a3:00000000 a4:00000000 a5:00000000 a6:00000000 a7:00000000 s2:00000000 s3:00000000 s4:00000000 s5:00000000 s6:00000000 s7:00000000 s8:00000000 s9:00000000 s10:00000000 s11:00000000 t3:00000000 t4:00000000 t5:00000000 t6:00000000
PC: 80000008 [0x00000000] Z:00000000 ra:000000aa sp:000000bb gp:00000000 tp:00000000 t0:00000000 t1:00000000 t2:00000000 s0:00000000 s1:00000000 a0:00000000 a1:83fff940 a2:00000000 a3:00000000 a4:00000000 a5:00000000 a6:00000000 a7:00000000 s2:00000000 s3:00000000 s4:00000000 s5:00000000 s6:00000000 s7:00000000 s8:00000000 s9:00000000 s10:00000000 s11:00000000 t3:00000000 t4:00000000 t5:00000000 t6:00000000
obijuan@JANEL:~/Develop/mini-rv32ima$ 

Vemos que al ejecutarse la primera instrucción (en la dirección 0x80000000) se pone ra a 0xaa (x1). Y con la siguiente instrucción sp (x2) a 0xbb... ¡Ya simulo!

Con esto puedo hacer pruebas...

2024-12-14

Binutils

Las BINutils de GNU tienen muchas utilidades para trabajar con código máquina, ensamblar, desensamblar... Quiero aprender a utilizarlas. He visto que en ubuntu se pueden instalar muy fácilmente de esta manera

sudo apt install binutils-riscv64-unknown-elf

Hay documentación de las binutils en estos enlaces:

Biblioteca libBFD

Biblioteca: Binary File Descriptor

Esta biblioteca contiene todo lo necesario para trabajar con ficheros objeto, que están en código máquina. Todas las herramientas que tienen que realizar operaciones con ficheros objetos usan esta biblioteca

Voy a leer la documentación para aprender más

No he encontrado mucha información que me interese. Hay mucha información para programar en C y hacerte tus aplicaciones, pero de momento no me interesa

Binutils

Voy a echar un vistazo a este manual:

Aquí se describen todas las utilidades... Voy a elegir alguna

Objdump

Esta utilidad sirve para mostrar información sobre ficheros objetos (y ejecutables)

Partimos de este programa de prueba en ensamblador:

  • addi.s:
.text
	
  addi x1,x0,0xaa
  addi x2,x0,0xbb

Lo ensamblamos con el Rars 1.6 desde la línea de comandos: java -jar rars1_6.jar a dump .text Binary addi.bin addi.s

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ java -jar rars1_6.jar a  dump .text Binary addi.bin addi.s
RARS 1.6  Copyright 2003-2019 Pete Sanderson and Kenneth Vollmar

Para desensamblar se utiliza -d. Pero si lo hacemos directamente se obtiene un error:

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -d addi.bin
riscv64-unknown-elf-objdump: addi.bin: file format not recognized

Hay que espeficiar el formato del fichero objeto. Objdump normalmente detecta este formato automáticamente, pero en este caso tenemos un fichero binario, sin ninguna cabecera con información

Para conocer todos los formatos y arquitecturas de Objdump usamos el parámetro -i

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -i
BFD header file version (2.42-1ubuntu1+6) 2.42
elf64-littleriscv
 (header little endian, data little endian)
  riscv
elf32-littleriscv
 (header little endian, data little endian)
  riscv
elf32-bigriscv
 (header big endian, data big endian)
  riscv
elf64-bigriscv
 (header big endian, data big endian)
  riscv
pei-riscv64-little
 (header little endian, data little endian)
  riscv
elf64-little
 (header little endian, data little endian)
  riscv
elf64-big
 (header big endian, data big endian)
  riscv
elf32-little
 (header little endian, data little endian)
  riscv
elf32-big
 (header big endian, data big endian)
  riscv
srec
 (header endianness unknown, data endianness unknown)
  riscv
symbolsrec
 (header endianness unknown, data endianness unknown)
  riscv
verilog
 (header endianness unknown, data endianness unknown)
  riscv
tekhex
 (header endianness unknown, data endianness unknown)
  riscv
binary
 (header endianness unknown, data endianness unknown)
  riscv
ihex
 (header endianness unknown, data endianness unknown)
  riscv
plugin
 (header little endian, data little endian)

         elf64-littleriscv elf32-littleriscv elf32-bigriscv elf64-bigriscv 
   riscv elf64-littleriscv elf32-littleriscv elf32-bigriscv elf64-bigriscv

         pei-riscv64-little elf64-little elf64-big elf32-little elf32-big srec 
   riscv pei-riscv64-little elf64-little elf64-big elf32-little elf32-big srec

         symbolsrec verilog tekhex binary ihex plugin 
   riscv symbolsrec verilog tekhex binary ihex ------

Para desensamblar entonces hay que usar -b binary para indicar que el fichero está en formato binario (y por tanto no tiene cabeceras) y -m riscv. Además hay que usar -D para indicar que desensamble TODAS las secciones. Como el binario no tiene cabecera, supone por defecto que son datos (y por defecto los datos no se desensamblan)

El comando para desensamblar es: riscv64-unknown-elf-objdump -b binary -m riscv -D -d addi.bin

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -b binary -m riscv -D -d addi.bin

addi.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:   0aa00093                li      ra,170
   4:   0bb00113                li      sp,187

Utilizando la opción -M no-aliases no se visualizan las pseudoinstrucciones, sino las instrucciones básicas:

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -b binary -m riscv -D -d  -M no-aliases  addi.bin

addi.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:   0aa00093                addi    ra,zero,170
   4:   0bb00113                addi    sp,zero,187

He visto en la documentación una opción para mostrar los registros con valores numéricos en vez de los nombres de la ABI, pero no me lo detecta. No sé si es porque en esta versión NO está implementando (que podría ser...)

La opción es -M gpr-names=numeric

Al probarla sale esto:

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -b binary -m riscv -D -d  -M no-aliases  -M gpr-names=numeric  addi.bin

addi.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:   BFD: unrecognized disassembler option: gpr-names
0aa00093                addi    ra,zero,170
   4:   0bb00113                addi    sp,zero,187

La versión que tengo instalada de las binutils es:

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -v
GNU objdump (2.42-1ubuntu1+6) 2.42
Copyright (C) 2024 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

La documentación que estoy leyendo es para la 2.43.... podría ser eso... o no

Con la opción --disassembler-color=on sale el código con resaltado de sintáxis...

Este es el comando que voy a usar para desensamblar:

riscv64-unknown-elf-objdump -b binary -m riscv -D -d  -M no-aliases --disassembler-color=on  addi.bin

OK, ya lo he encontrado, el parámetro es -M numeric. Con esto salen los registros como x0, x1, etc... en vez de los nombres de la ABI:

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-objdump -b binary -m riscv -D -d  -M no-aliases -M numeric --disassembler-color=on   addi.bin

addi.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:   0aa00093                addi    x1,x0,170
   4:   0bb00113                addi    x2,x0,187

Para mostrar los nemónicos en hexadecimal no encuentro la opción... bueno, de momento puedo vivir sin ello..

Size

Esta es la utilidad para mostrar el tamaño de las secciones

obijuan@JANEL:~/Develop/Learn-RISCV/Log/2024-12-14$ riscv64-unknown-elf-size --target=binary addi.bin
   text    data     bss     dec     hex filename
      0       8       0       8       8 addi.bin

Objcopy

Utilidad para pasar el fichero objeto de un formato a otro

2025-Jan-08

Hoy he recibido el libro "RISC-V Assembly Language" de Antohony J. Dos Reis. El libro es muy básico. Tal vez pensado para gente que empieza desde cero. Utiliza sus propias herramientas: El ensamblador rv, que te lo envía por correo. No he encotrado las fuentes... una pena. El contenido del fichero recibido lo he metido en este repo: rv

Los experimentos los estoy poniendo en esta otra parte de la wiki: RISCV Assembly Language

Clone this wiki locally