Thank you for your interest in Plan 9. I hope you will continue to study
it. There are many valuable lessons in the code, which was created by the
group that invented C, and, of course, Unix.

On Fri, Aug 29, 2025 at 9:39 AM José J. Cabezas Castillo <
[email protected]> wrote:

> Hi,
>
> My name is José J. many years ago, in a college operating systems class,
> the professor mentioned Plan 9 as a curiosity — an OS where "everything is
> a file". Recently, I’ve had more time, so I installed 9front from the ISO
> on a few machines to explore and learn.
>
> To get started with RISC-V, I tried creating a simple "Hello World" for
> TinyEMU. I managed to output some characters using HTIF:
>
> ---h.c---
> #include <u.h>
>
> #define         HTIFADDR_BASE                   0x40008000
>
> void
> f(void)
> {
>         *((volatile uvlong *) HTIFADDR_BASE) = 0x0101000000000031ull;
>         *((volatile uvlong *) HTIFADDR_BASE) = 0x0101000000000032ull;
>         *((volatile uvlong *) HTIFADDR_BASE) = 0x0101000000000033ull;
>         for(;;);
> }
> ---
> Compiled with:
> %ic -FVw h.c
> %il -l -H 1 -T0x80000000 -o h32.bin h.i
>
> Then I wanted to improve it to print "Hello World", following this video
> and GitHub repo:
>
>    - https://www.youtube.com/watch?v=HC7b1SVXoKM
>    - https://github.com/chuckb/riscv-helloworld-c/
>
> The example is for Linux, but I tried to adapt it for Plan 9. Using QEMU
> in Linux, I was able to print characters like before (with just h.c and
> no functions). However, when I switched to using functions (helloq.c) and
> a loader (chuck.s), it stopped working.
>
> Here is the code:
>
> ---helloq.c---
>
> #include <u.h>
>
> #define UART_BASE               0x10000000
>
> void
> uartputc(char c)
> {
>         *((volatile ulong *) UART_BASE) = c;
> }
>
> void
> printstr(char *s)
> {
>         while (*s)
>                 uartputc(*s++);
> }
>
> void
> main(void)
> {
>         printstr("Hello world\n");
>         for (;;);
> }
> ---
> ---chuck.s---
> TEXT start(SB), $0
>         /* set stack pointer */
>         MOVW    $0x80020000, R2
>         /* set frame pointer */
>         ADD     R0, R2, R8
>         /* call main */
>         JAL     R1, main(SB)
> ---
> Compiled with:
> ic -FVSw helloq.c
> il -l -a -H 1 -T0x80000000 -R4 -o helloq.bin chuck.i helloq.i
>
> The assembler generated is:
>  80000000:              (1)     TEXT    start+0(SB),$4
>
> * 80000000: 1161         (1)     ADD     $-8,R2 80000002: c006         (1)
>     MOVW    R1,0(R2)*
>  80000004: 80020137     (3)     MOV     $-2147352576,R2
>  80000008: 00010433     (6)     ADD     R0,R2,R8
>  8000000c: 2091         (9)     JAL     ,R1,main+80000050(BRANCH)
>  8000000e: 0001         (0)     ADD     $0,R0,R0
>  80000010:              (74)    TEXT    uartputc+0(SB),R0,$-4
>  80000010: 10000637     (74)    MOV     $268435456,R12
>  80000014: 01841593 4185d593(74)        MOVB    R8,R11
>  8000001c: 01859513 41855513(76)        MOVB    R11,R10
>  80000024: c208         (76)    MOVW    R10,0(R12)
>  80000026: 8082         (76)    JMP     ,0(R1)
>  80000028:              (80)    TEXT    printstr+0(SB),R0,$4
>  80000028: 1161         (80)    ADD     $-8,R2
>  8000002a: c006         (80)    MOVW    R1,0(R2)
>  8000002c: 84a2         (80)    MOV     R8,R9
>  8000002e: 00048583     (82)    MOVB    0(R9),R11
>  80000032: c999         (82)    BEQ     R11,80000048(BRANCH)
>  80000034: 00148613     (83)    ADD     $1,R9,R12
>  80000038: c632         (83)    MOVW    R12,s+0(FP)
>  8000003a: 00048403     (83)    MOVB    0(R9),R8
>  8000003e: 3fc9         (83)    JAL     ,uartputc+80000010(BRANCH)
>  80000040: 44b2         (83)    MOVW    s+0(FP),R9
>  80000042: 00048583     (82)    MOVB    0(R9),R11
>  80000046: f5fd         (82)    BNE     R11,80000034(BRANCH)
>  80000048: 4082         (83)    MOVW    0(R2),R1
>  8000004a: 0121         (83)    ADD     $8,R2
>  8000004c: 8082         (83)    JMP     ,0(R1)
>  8000004e: 0001         (0)     ADD     $0,R0,R0
>  80000050:              (87)    TEXT    main+0(SB),R0,$4
>  80000050: 1161         (87)    ADD     $-8,R2
>  80000052: c006         (87)    MOVW    R1,0(R2)
>  80000054: 80018413     (89)    MOV     $.string<>+0(SB),R8
>  80000058: 3fc1         (89)    JAL     ,printstr+80000028(BRANCH)
>  8000005a: a001         (90)    JMP     ,30(APC)
> ----
>
> However, when debugging with GDB in QEMU, I found that the instruction at
> address *0x80000002* causes the PC (program counter) to reset, and
> execution does not continue. I believe these extra instructions are added
> by the loader automatically, but I don’t know how to prevent this.
>
> I also tried using l.s from the 9legacy compiler sources, but had the same
> result. I’ve been reading through start.s from the RISC-V kernel and
> looking at the mkfile, suspecting I might need to pass specific options to
> compile correctly, but there are too many and I don’t fully understand them
> yet.
>
> Can someone explain how to compile without these extra instructions, or
> why the PC is being reset and how to avoid it?
>
> Thanks in advance, and apologies for my English and the length of this
> email.
>
> Best regards,
> José J.
>
>
> *9fans <https://9fans.topicbox.com/latest>* / 9fans / see discussions
> <https://9fans.topicbox.com/groups/9fans> + participants
> <https://9fans.topicbox.com/groups/9fans/members> + delivery options
> <https://9fans.topicbox.com/groups/9fans/subscription> Permalink
> <https://9fans.topicbox.com/groups/9fans/T3f252d4d7c5389ee-Maed6f4ac773a82fcbebf2b64>
>

------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T3f252d4d7c5389ee-M7443e2eed479486fd6a55cc6
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to