Arsalan Shahid

Assembly Programming in MIPS32 using real-world RISC-based Ci20 Microprocessor

My dear reader, how are you? السلام عليكم

Education is what remains after one has forgotten what one has learned in school – Albert Einstein

In this post, I explain the assembly language programming in MIPS32 on a real-world RISC based microprocessor. This post also contains the working examples of simple assembly programs running on ci20, i.e., a Creator Dev embedded processor platform.

Introduction to ci20 board

Embedded system

An embedded processor is a type of microprocessor designed into a system to control electrical and mechanical functions. Embedded processors are usually simple in design, limited in computational power and I/O capabilities, and have minimal power requirements.

What is ci20?

A MIPS32 based embedded processor.

The MIPS Creator Ci20 is a high performance, fully-featured embedded development board for Linux and Android that can help you create applications for fast-growing markets such as IoT, wearables, mobile, and gaming. It incorporates an Ingenic JZ4780 SoC which includes a 1.2GHz dual-core MIPS32 processor and Imagination PowerVR SGX540 GPU.

Detailed specifications are given below:

-1.2GHz dual-core XBurst MIPS32 JZ4780 SoC with PowerVR SGX540 GPU and FPU
– GPU supports MPEG-4, H.264, VP8, MPEG-2, and RV9
– On-board 1GB DDR3 SDRAM
– On-board 8GB NAND Flash memory
– On-board IW8103 IEEE 802.11b/g/n WiFi and Bluetooth 4.0 wireless module
– On-board DM9000C Ethernet controller and PHY
– Infrared (IrDA) receiver for remote control
– Reset and Boot pushbuttons
-Jumper link for Boot mode (SD card or Flash)
– 4 x status LEDs
– USB activity LED
– HDMI socket for 1080p video
– SD card slot
– USB-A socket for USB 2.0 OTG
– USB-A socket for USB 2.0 Host
– USB mini-B socket for power supply
– RJ45 socket for 10/100 Ethernet LAN
– 24-pin ITU-645 camera connector
– 3.5mm stereo audio output and microphone input jack socket
– 26-pin Primary Expansion header for GPIO/SPI/I²C, Raspberry Pi compatible
– 16-pin Secondary Expansion header for ADC, touch sensing and battery monitor
– 4-pin UART header
-14-pin MIPS EJTAG header
– Power supply: +5Vdc @ 1A via 1.7mm barrel jack socket or USB mini-B socket
– Dimensions: 100 x 92mm

Overview of ci20

How to power on Ci20?

Just plug it in.

Yes! Out of the box, the CI20 is ‘ready to go’. By default, it will boot the OS image (Debian7).

How to use Ci20?

There are two options:

How to use ci20 as a headless processor?

The open-ssh server is already installed on Ci20. Using your laptop or PC (i.e., client), you can ssh in the board provided the IP is known.

How to log-in as root?

Type the following command in the terminal

$ su root

(when prompted for the password, enter ‘ci20’)

Assembly programming on ci20

First example program

$ vim.tiny firstprogram.s

# press “i” to insert text in the file


        .global __start


        li      $a0,    50
        li      $v0,    4001

(press Esc and then :wq to write changes in the file and exit)

$ as firstprogram.s -o firstprogram.o

# AS is a GNU assembler. Details: DirectMe 
$ ld firstprogram.o -o firstprogramexe

# And run it.

$ ./firstprogramexe
$ echo $?
# The computer will output 50.


Use registers with numbers

$ vim.tiny secondprogram.s

        .global __start


        li      $4,    50
        li      $2,    4001

Compile and run the program using the aforementioned steps.

Linux syscalls for 32-bit OS

For a complete list of available Linux syscalls for MIPS32 check the link DirectMe.

hello world program on ci20


string:       .asciiz "Hello World!\n"


        .global __start


        li      $a0,    0
        la      $a1,    string
        li      $a2,    13
        li      $v0,    4004

        li      $a0,    3
        li      $v0,    4001
$ as helloworld.s -o helloworld.o
$ ld helloworld.o -o helloworld
$ ./ helloworld

# prints "Hello World!"
$ echo $?

# prints "3"

Use words for calling syscall instead of numbers

#include <regdef.h>
#include <sys/syscall.h>


string:       .asciiz "Hello World!\n"
length:         .word   13


        .global __start


        li      a0, 1
        la     a1, string
        lw    a2, length
        li      v0, SYS_write

        li      a0, 6
        li      v0, SYS_exit
$ gcc -S wordssyscall.S > wordssyscall.s
# note the capital S and small s

Check the output of preprocessing

$ more wordssyscall.s
$ as wordssyscall.s -o wordssyscall.o
$ ld wordssyscall.o -o wordssyscallexe
$ ./wordssyscallexe

How to do a loop?

#include <sys/regdef.h>
#include <sys/syscall.h>

        .align  2
        hello:  .asciiz  "Hello World!\n"
        .align          4
        length:         .word 13


        .global __start


        move    s1, $0
        addi    s1, s1, 9


        move    a0, $0
        la      a1, hello
        lw      a2, length
        li      v0, SYS_write

        addi    s1, -1
        bne     s1,0, __loop

        li      a0, 6
        li      v0, SYS_exit
$ gcc -S helloworldloop.S > helloworldloop.s

# Note the capital S and small s

# Check the output of preprocessing

$ more helloworldloop.s

$ as helloworldloop.s -o helloworldloop.o
$ ld helloworldloop.o -o helloworldloopexe
$ ./helloworldloopexe

I hope you find this post useful. If you find any errors or feel any need for improvement, let me know in your comments below.

Signing off for today. Stay tuned and I will see you next week! Happy learning.

Exit mobile version