| 1. | ARM 64-bit Assembly |
| 2. | Simplest programs |
| 3. | Integers |
| 4. | Main memory |
| 5. | Arrays |
| 6. | Branching and loops |
| 7. | Functions |
| 8. | Floating point |
1. ARM 64-bit Assembly Language
1. Introduction
1.1. Raspberry Pi OS has everything we need
If you have a Raspberry Pi 4 that runs its newest official 64-bit operating system called Raspberry Pi OS, then you do not need any other software. Your Raspberry Pi 4 already has the GCC compiler and the assembler. Assembler is a program that turns the code written in the assembly language into a program written in the machine language.
1.2. Code auto-grader
On this website, you can practice without writing the entire programs. You can write only parts of the code in the assembly language. This will be helpful in the beginning. The introductory exercises will ask for only few lines in the assembly language. The auto-grader will add the remaining commands, call the compiler and the assembler, and execute the obtained program.
1.3. Making entire programs
Once we are ready, we will move from this website's code auto-grader to your Raspberry Pi. We will start with very simple programs. They will be simpler than anything you have ever written. These first programs will not even print on the screen. They will only return an exit code. They will do that silently. We will have to use a separate command to ask the operating system to display the exit code.
Even these simplest programs would require us to go through a somewhat lengthy process. We will first need to write a program in the assembly language. After the program is written, we will have to use the gcc compiler to translate the program from the assembly language into the machine code. Then, we will need to execute the machine code. Finally, we will need to read the exit code that the program sent to the operating system.
2. Introduction to registers
2.1. Variables in high-level languages
Python, C, Java, C++, and other high-level languages had variables. We were allowed to use a lot of names for our variables. The best names were a, b, and c. However, we were also allowed to use the names that were not as good as these.
We were also allowed to use the commands such as a=7; b=27; c=37; and c=a+b;
The assembler doesn't let us use the variables. We also won't be allowed to write c=a+b;.
2.2. Registers in CPU
The central processing unit (known as CPU) does all the calculations. The CPU has several registers, and the calculations can be done only on numbers that are inside the registers.
We are not allowed to do operations on anything that is not a register.
Raspberry Pi 4 has 32 registers that can handle integer values. They are called
X0, X1, X2, , ..., X28, X29, LR, SPEach of them can hold a 64-bit integer. The registers
LR and SP are special. They are called link register and stack pointer. They are very important and we will not touch them until we learn what they do. If we mess up with these registers before we learn what they are, then we will crash our programs with probability \(95\%\).
2.3. Arithmetic operations
We will now learn how to write the instructions that perform basic arithmetic operations. The arithmetic operations can be performed only on registers.
2.3.1. Addition
We can add values from two registers and store the result in the third. The following command will add the values inside X3 and X7 and store the result in X5.
ADD X5, X3, X7
The instruction above is analogous to the instruction X5=X3+X7.
2.3.2. Subtraction
To perform the subtraction X5=X3-X7, we have to give the following instruction in assembly language:
SUB X5, X3, X7
2.3.3. Multiplication
The multiplication X5=X3*X7 is achieved with the assembly instruction
MUL X5, X3, X7
2.3.4. Division
The division cannot be done. The CPU does not have a way to divide two integers. We will have to write a function that performs integer division. That task is not easy at all. We will write such function later - once we learn how to write functions.
The CPU has an instruction for the division of real numbers, but not for the division of integers. We will not learn that instruction now because we are not ready to talk about real numbers yet. We will learn later that real numbers have to be stored in special registers that are different from X0, ..., X30. And we will have to learn about floating point representation of real numbers. These things have to wait.
3. Auto-grader practice
We know three instructions in the assembly language. They are ADD, SUB, and MUL
This is enough for our first practice problems.
Here are few rules of the assembly language:
- Each command must be in a separate line.
- You are allowed to write comments. The rules for comments are pretty much the same as in C and C++. Multi-line comments are placed between
/*and*/. The GCC compiler is fine with single line comments, but other compilers may complain. It is best not to use single line comments. - Each of the fundamental instructions has 4 components: The name of the instruction, and the three registers. The three registers must be separated by commas. Optionally, the space characters (and/or tab characters) can be inserted before and after the commas. The name of the instruction and the name of the first register must be separated by one or more space characters (or tab characters).
- Additional space characters do not have any effect. It is consider a good practice to put space characters (or tab symbols) in such a way that the assembly code looks like a matrix with 4 columns.
- The assembly language is not case sensitive. Thus,
addis the same asADD. Also,x1is the same asX1.
3.1. Problem with a solution
Please read the following problem and its solution. Then, have fun solving the problems in the auto-grader.
X0. The numbers \(a\), \(b\), and \(c\) are already placed in the registers X1, X2, and X3.
3.2. Practice
Write a code that calculates
\(a^2+b^2\)
and stores the result in the register X0. The integers \(a\) and \(b\) are already placed in the registers X1 and X2.
You should only write the code that replaces the text /* ??? */ in the listing below.
/* ***************************************** Autograder's program that reads the numbers a and b from the user input and stores them in the registers X1 and X2 ********************************************* */ /* ??? */ /* ***************************************** Autograder's program that prints the content of the register X0 ********************************************* */
Write a code that calculates
\(a+bx+cx^2+dx^3\)
and stores the result in the register X0. The integers \(a\), \(b\), \(c\), \(d\), and \(x\) are already placed in the registers X1, X2, X3, X4, and X5.
Hint: Try to use multiplication only 3 times! Once you spot the trick that can achieve this, you can write a very short code. The obtained code will not only be short, but also very fast. The multiplication is a much slower instruction than addition.
4. Summary of basic facts about registers
This was an introductory section. We did not say everything that there is to be said about registers. Our focus was limited to only the most fundamental facts that are necessary for writing the first programs.
- Each of the registers
X0,X1,X2,...,X29,LR, andSPhas size64bits. - The register
LRcan also be accessed with the identifierX30. The registerLR(orX30) is called link register. Do not put anything in this register before you learn about branch and link instructions. Otherwise, your program will crash in one way or another. - The register
SPis called stack pointer. You cannot access it with the nameX31. Do not put anything in this register before you learn about the program stack. - There are other integer registers called
W0,W1,...,W29,W30. They have size32bits, and they share the space with registersX0,...,X30. The registerWiis the lower half of the registerXi. Never use the registerW30.
5. MOV
The instruction
MOV X1, X2copies the value from the register
X2 and places it into the register X1.
6. Immediate values
The integers 0, 1, ..., 255 can be arguments of the arithmetic operations and of the MOV instruction. They are called immediate values.
An immediate value can only be the last argument of an instruction.
The instruction MOV is one of the most commonly used instructions in the assembly language. However, not every CPU architecture has the MOV instruction. When a CPU does not have MOV, then the assembler replaces the command MOV X1, X2 with ADD X1, X2, 0.
7. Practice problems
Write a code that swaps the contents of the registers X1 and X2.
Write a code that swaps the contents of the registers X7 and X8 without using any other register.