Table Of ContentAn Introduction to
Assembly Programming
with RISC-V
Prof. Edson Borin
Institute of Computing
Unicamp
1st edition
An Introduction to Assembly Programming
with RISC-V
2
Copyright c 2021 Edson Borin
All rights reserved. This book or any portion thereof may notbe reproduced
orusedinany mannerwhatsoever withouttheexpresswrittenpermission of
the author except for the use of brief quotation in a book review.
ISBN:978-65-00-15811-3
First edition 2021
Edson Borin
Institute of Computing - University of Campinas
Av. Albert Einstein, 1251
Cidade Universita´ria Zeferino Vaz
Bara˜o Geraldo - Campinas - SP - Brasil
www.ic.unicamp.br/~edson
13083-852
An updatedversionof this book and other material maybe available at:
www.riscv-programming.org
3
Foreword
This book focuses on teaching the art of programming in assembly language, using
the RISC-V ISA as the guiding example. Towards this goal, the text spans, at an
introductory level,the organizationof computing systems,describes the mechanics of
how programs are created and introduces basic programming concepts including both
user level and system programming. The ability to read and write code in low-level
assembly languageis apowerful skill to be able tocreate highperformance programs,
and to access features of the machine that are not easily accessible from high-level
languages such as C, Java or Python, for example to control peripheraldevices.
The book introduces the organization of computing systems, and the mechan-
ics of creating programs and converting them to machine-readable format suitable
for execution. It also teaches the components of a program, or how a programmer
communicates her intent to the system via directives, data allocation primitivesand
finally the ISA instructions, and their use. Basic programming concepts of control
flow, loopsas wellas the runtimestackare introduced.
Next the book describes the organization of code sequences into routines and
subroutines, to composea program. The text also addresses issues related tosystem
programming, including notions of peripheralcontroland interrupts.
This text,and ancillary teachingmaterials, has beenused in introductory classes
at the University of Campinas, Brazil (UNICAMP) and has undergone refinement
and improvement for several editions.
Mauricio Breternitz
Principal Investigator & Invited AssociateProfessor
ISTAR ISCTE Laboratory
ISCTE Instituto Universitario de Lisboa
Lisbon,Portugal
4
Notices:
• Documentversion: May 9, 2022
• Please, reporttyposandotherissuesto Prof. EdsonBorin ([email protected].
br).
5
Contents
Foreword 4
Glossary 11
Acronyms 14
I Introduction to computer systems and assembly language
1
1 Execution of programs: a 10,000 ft overview 2
1.1 Main components of computers . . . . . . . . . . . . . . . . . . . . . . 2
1.1.1 The main memory . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 The CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Executing program instructions . . . . . . . . . . . . . . . . . . . . . . 4
1.3 The boot process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Data representation on modern computers 6
2.1 Numeral Systems and the Positional Notation . . . . . . . . . . . . . . 6
2.1.1 Converting numbersbetweenbases . . . . . . . . . . . . . . . . 8
2.2 Representing numberson computers . . . . . . . . . . . . . . . . . . . 11
2.2.1 Unsigned numbers . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2.2 Signed numbers. . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.3 Binary arithmetic and Overflow. . . . . . . . . . . . . . . . . . 14
2.2.4 Integer Overflow . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3 Representing text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4 Organizing data on the memory. . . . . . . . . . . . . . . . . . . . . . 18
2.4.1 Texts on the main memory . . . . . . . . . . . . . . . . . . . . 18
2.4.2 Numberson the main memory . . . . . . . . . . . . . . . . . . 19
2.4.3 Arrays on the main memory . . . . . . . . . . . . . . . . . . . . 19
2.4.4 Structs on the main memory . . . . . . . . . . . . . . . . . . . 21
2.5 Encodinginstructions . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3 Assembly, object, and executable files 24
3.1 Generating native programs . . . . . . . . . . . . . . . . . . . . . . . . 24
3.1.1 Inspectingthe contents of object and executable files . . . . . . 26
3.2 Labels,symbols, references, and relocation . . . . . . . . . . . . . . . . 27
3.2.1 Labelsand symbols . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2.2 References to labelsand relocation . . . . . . . . . . . . . . . . 28
3.2.3 Undefined references . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.4 Global vs localsymbols . . . . . . . . . . . . . . . . . . . . . . 31
3.2.5 The program entry point . . . . . . . . . . . . . . . . . . . . . 32
3.3 Program sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.4 Executable vs object files . . . . . . . . . . . . . . . . . . . . . . . . . 36
6
4 Assembly language 37
4.1 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2 Assembly instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3 Immediate values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.4 Symbolnames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.5 Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.6 The locationcounterand the assemblingprocess . . . . . . . . . . . . 42
4.7 Assembly directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.7.1 Adding values to the program . . . . . . . . . . . . . . . . . . . 44
4.7.2 The .section directive . . . . . . . . . . . . . . . . . . . . . . 46
4.7.3 Allocatingvariables on the .bss section . . . . . . . . . . . . . 47
4.7.4 The .set and .equ directives . . . . . . . . . . . . . . . . . . . 48
4.7.5 The .globl directive. . . . . . . . . . . . . . . . . . . . . . . . 49
4.7.6 The .align directive. . . . . . . . . . . . . . . . . . . . . . . . 49
II User-level programming 51
5 Introduction 52
6 The RV32I ISA 53
6.1 Datatypesand memory organization . . . . . . . . . . . . . . . . . . . 54
6.2 RV32I registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.3 Load/Store architecture . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.4 Pseudo-instructions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.5 Logic, shift, and arithmetic instructions . . . . . . . . . . . . . . . . . 56
6.5.1 Instructions syntax and operands . . . . . . . . . . . . . . . . . 57
6.5.2 Dealing with large immediate values . . . . . . . . . . . . . . . 57
6.5.3 Logic instructions . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.5.4 Shift instructions . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.5.5 Arithmetic instructions . . . . . . . . . . . . . . . . . . . . . . 61
6.6 Data movement instructions . . . . . . . . . . . . . . . . . . . . . . . . 63
6.6.1 Load instructions . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.6.2 Store instructions . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.6.3 Data movement pseudo-instructions . . . . . . . . . . . . . . . 68
6.7 Control-flow instructions . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.7.1 Conditional control-flow instructions . . . . . . . . . . . . . . . 69
6.7.2 Direct vs indirect control-flow instructions . . . . . . . . . . . 71
6.7.3 Unconditional control-flow instructions. . . . . . . . . . . . . . 72
6.7.4 System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.8 Conditional set instructions . . . . . . . . . . . . . . . . . . . . . . . . 74
6.9 Detecting overflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.10 Arithmetic on multi-word variables . . . . . . . . . . . . . . . . . . . . 75
7 Controlling the execution flow 77
7.1 Conditional statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
7.1.1 if-then statements . . . . . . . . . . . . . . . . . . . . . . . . 77
7.1.2 Comparing signed vs unsigned variables . . . . . . . . . . . . . 77
7.1.3 if-then-else statements . . . . . . . . . . . . . . . . . . . . . 78
7.1.4 Handling non-trivial boolean expressions. . . . . . . . . . . . . 79
7.1.5 Nested if statements . . . . . . . . . . . . . . . . . . . . . . . . 80
7.2 Repetitionstatements . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.2.1 while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.2.2 do-while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.2.3 for loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7.2.4 Hoisting loop-invariantcode . . . . . . . . . . . . . . . . . . . . 83
7.3 Invoking and returning from routines . . . . . . . . . . . . . . . . . . . 83
7.3.1 Returning values from functions . . . . . . . . . . . . . . . . . 84
7.4 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
7
7.4.1 Searching for the maximum value on an array . . . . . . . . . . 85
8 Implementing routines 87
8.1 The program memory layout . . . . . . . . . . . . . . . . . . . . . . . 87
8.2 The program stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
8.2.1 Typesof stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.3 The ABI and software composition . . . . . . . . . . . . . . . . . . . . 91
8.4 Passing parameters to and returning values from routines . . . . . . . 91
8.4.1 Passing parameters to routines . . . . . . . . . . . . . . . . . . 91
8.4.2 Returning values from routines . . . . . . . . . . . . . . . . . . 93
8.5 Value and reference parameters . . . . . . . . . . . . . . . . . . . . . . 93
8.6 Global vs localvariables . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.6.1 Allocatinglocalvariables on memory . . . . . . . . . . . . . . . 96
8.7 Register usage policies . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.7.1 Caller-saved vs Callee-saved registers . . . . . . . . . . . . . . . 99
8.7.2 Saving and restoring the return address . . . . . . . . . . . . . 100
8.8 Stack Frames and the Frame Pointer . . . . . . . . . . . . . . . . . . . 100
8.8.1 Stack Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.8.2 The Frame Pointer . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.8.3 Keeping the stack pointer aligned. . . . . . . . . . . . . . . . . 102
8.9 Implementing RISC-V ilp32 compatible routines . . . . . . . . . . . . 102
8.10 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.10.1 Recursiveroutines . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.10.2 The standard “C” library syscall routines . . . . . . . . . . . . 104
III System-level programming 106
9 Accessing peripherals 107
9.1 Peripherals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.2 Interacting with peripherals . . . . . . . . . . . . . . . . . . . . . . . . 108
9.2.1 Port-mappedI/O. . . . . . . . . . . . . . . . . . . . . . . . . . 109
9.2.2 Memory-mappedI/O . . . . . . . . . . . . . . . . . . . . . . . 110
9.3 I/O operationson RISC-V. . . . . . . . . . . . . . . . . . . . . . . . . 111
9.4 Busy waiting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
10 External Interrupts 114
10.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
10.1.1 Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.2 External Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.2.1 Detecting external interrupts . . . . . . . . . . . . . . . . . . . 117
10.2.2 Invoking the properinterruptservice routine . . . . . . . . . . 118
10.3 Interruptson RV32I . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
10.3.1 Controland Status Registers . . . . . . . . . . . . . . . . . . . 120
10.3.2 Interruptrelated Controland Status Registers . . . . . . . . . 121
10.3.3 InterruptHandling Flow . . . . . . . . . . . . . . . . . . . . . . 122
10.3.4 Implementingan interruptservice routine . . . . . . . . . . . . 123
10.3.5 Setting up the Interrupt Handling Mechanism. . . . . . . . . . 124
11 Software Interrupts and Exceptions 127
11.1 Privilege Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
11.2 Protecting the system . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
11.3 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
11.4 Software Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
11.5 Protecting RISC-V systems . . . . . . . . . . . . . . . . . . . . . . . . 130
11.5.1 Changing the privilege mode . . . . . . . . . . . . . . . . . . . 130
11.5.2 Configuring the exception and software interrupt mechanisms . 131
11.5.3 Handling illegal operations . . . . . . . . . . . . . . . . . . . . 131
11.5.4 Handling system calls . . . . . . . . . . . . . . . . . . . . . . . 132
8
A RV32IM ISA reference card 134
9
10