Skip to content
Permalink
Browse files

Clean up some formatting.

  • Loading branch information
Richard Drake
Richard Drake committed Feb 4, 2020
1 parent 09cf99f commit 84322489df702813aaa67ad3dc738beb0ce553e2
Showing with 15 additions and 14 deletions.
  1. +13 −12 site/content/lab/arm.md
  2. +2 −2 site/content/lab/ssdisplay1/index.md
@@ -23,7 +23,7 @@ main: /* This is main */
Create a file called first.s and write the contents shown above. Save it.
To assemble the file type the following command (write what comes after $ ).
To assemble the file type the following command (write what comes after `$`).
{{< highlight bash >}}
$ as -o first.o first.s
@@ -45,22 +45,23 @@ It should do nothing. Yes, it is a bit disappointing, but it actually does somet
{{< highlight bash >}}
$ ./first ; echo $?
2
{{< /highlight >}}
Great! That error code of 2 is not by chance, it is due to that #2 in the assembler code.
# Well, what happened?
We cheated a bit just to make things a bit easier. We wrote a C main function in assembler which only does return 2;. This way our program is easier since the C runtime handled initialization and termination of the program for us. I will use this approach all the time.
We cheated a bit just to make things a bit easier. We wrote a C main function in assembler which only does `return 2;`. This way our program is easier since the C runtime handled initialization and termination of the program for us. I will use this approach all the time.
Let's review every line of our minimal assembler file.
These are comments. Comments are enclosed in /* and */. Use them to document your assembler as they are ignored. As usually, do not nest /* and */ inside /* because it does not work.
These are comments. Comments are enclosed in `/*` and `*/`. Use them to document your assembler as they are ignored. As usual, do not nest `/*` and `*/` inside `/*` because it does not work.
{{< highlight "ARM Assembly" >}}
.global main /* 'main' is our entry point and must be global */
{{< /highlight >}}
This is a directive for GNU Assembler. A directive tells GNU Assembler to do something special. They start with a dot (.) followed by the name of the directive and some arguments. In this case we are saying that main is a global name. This is needed because the C runtime will call main. If it is not global, it will not be callable by the C runtime and the linking phase will fail.
This is a directive for GNU Assembler. A directive tells GNU Assembler to do something special. They start with a dot (`.`) followed by the name of the directive and some arguments. In this case we are saying that main is a global name. This is needed because the C runtime will call main. If it is not global, it will not be callable by the C runtime and the linking phase will fail.
{{< highlight "ARM Assembly" >}}
.func main /* 'main' is a function */
@@ -72,34 +73,34 @@ Another GNU assembler directive. Here we state that main is a function. This is
main: /* This is main */
{{< /highlight >}}
Every line in GNU Assembler that is not a directive will always be like label: instruction. We can omit label: and instruction (empty and blank lines are ignored). A line with only label:, applies that label to the next line (you can have more than one label referring to the same thing this way). The instruction part is the ARM assembler language itself. In this case we are just defining main as there is no instruction.
Every line in GNU Assembler that is not a directive will always be like label: instruction. We can omit `label:` and instruction (empty and blank lines are ignored). A line with only `label:`, applies that label to the next line (you can have more than one label referring to the same thing this way). The instruction part is the ARM assembler language itself. In this case we are just defining main as there is no instruction.
{{< highlight "ARM Assembly" >}}
mov r0, #2 /* Put a 2 inside the register r0 */
{{< /highlight >}}
Whitespace is ignored at the beginning of the line, but the indentation suggests visually that this instruction belongs to the main function.
This is the mov instruction which means move. We move a value 2 to the register r0. In the next chapter we will see more about registers, do not worry now. Yes, the syntax is awkward because the destination is actually at left. In ARM syntax it is always at left so we are saying something like move to register r0 the immediate value 2. We will see what immediate value means in ARM in the next chapter, do not worry again.
This is the mov instruction which means move. We move a value `2` to the register `r0`. In the next chapter we will see more about registers, do not worry now. Yes, the syntax is awkward because the destination is actually at left. In ARM syntax it is always at left so we are saying something like move to register `r0` the immediate value `2`. We will see what immediate value means in ARM in the next chapter, do not worry again.
In summary, this instruction puts a 2 inside the register r0 (this effectively overwrites whatever register r0 may have at that point).
In summary, this instruction puts a `2` inside the register `r0` (this effectively overwrites whatever register `r0` may have at that point).
{{< highlight "ARM Assembly" >}}
bx lr /* Return from main */
{{< /highlight >}}
This instruction bx means branch and exchange. We do not really care at this point about the exchange part. Branching means that we will change the flow of the instruction execution. An ARM processor runs instructions sequentially, one after the other, thus after the mov above, this bx will be run (this sequential execution is not specific to ARM, but what happens in almost all architectures). A branch instruction is used to change this implicit sequential execution. In this case we branch to whatever lr register says. We do not care now what lr contains. It is enough to understand that this instruction just leaves the main function, thus effectively ending our program.
This instruction `bx` means branch and exchange. We do not really care at this point about the exchange part. Branching means that we will change the flow of the instruction execution. An ARM processor runs instructions sequentially, one after the other, thus after the `mov` above, this `bx` will be run (this sequential execution is not specific to ARM, but what happens in almost all architectures). A branch instruction is used to change this implicit sequential execution. In this case we branch to whatever `lr` register says. We do not care now what `lr` contains. It is enough to understand that this instruction just leaves the main function, thus effectively ending our program.
And the error code? Well, the result of main is the error code of the program and when leaving the function such result must be stored in the register r0, so the mov instruction performed by our main is actually setting the error code to 2.
And the error code? Well, the result of main is the error code of the program and when leaving the function such result must be stored in the register `r0`, so the `mov` instruction performed by our main is actually setting the error code to `2`.
# Registers
At its core, a processor in a computer is nothing but a powerful calculator. Calculations can only be carried using values stored in very tiny memories called registers. The ARM processor in a Raspberry Pi has 16 integer registers and 32 floating point registers. A processor uses these registers to perform integer computations and floating point computations, respectively. We will put floating registers aside for now and eventually we will get back to them in a future installment. Let’s focus on the integer registers.
Those 16 integer registers in ARM have names from r0 to r15. They can hold 32 bits. Of course these 32 bits can encode whatever you want. That said, it is convenient to represent integers in two's complement as there are instructions which perform computations assuming this encoding. So from now, except noted, we will assume our registers contain integer values encoded in two's complement.
Those 16 integer registers in ARM have names from `r0` to `r15`. They can hold 32 bits. Of course these 32 bits can encode whatever you want. That said, it is convenient to represent integers in two's complement as there are instructions which perform computations assuming this encoding. So from now, except noted, we will assume our registers contain integer values encoded in two's complement.
# Basic arithmetic
Almost every processor can do some basic arithmetic computations using the integer registers. So do ARM processors. You can ADD two registers. Let's retake our example from above:
Almost every processor can do some basic arithmetic computations using the integer registers. So do ARM processors. You can **add** two registers. Let's retake our example from above:
{{< highlight "ARM Assembly" >}}
/* -- sum01.s */
@@ -113,4 +114,4 @@ main:
bx lr
{{< /highlight >}}
If we compile and run this program the error code is, as expected, 7.
If we compile and run this program the error code is, as expected, `7`.
@@ -16,7 +16,7 @@ There are 128 different ouput that can be generated with a 7-segment display:

## The I<sup>2</sup>C bus

The HT16K33 7-segment display uses the I<sup>2</sup>C bus. An I<sup>2</sup>C bus can support up to 256 different devices (e.g. sensors, motors, outputs) at the same time. Each component has a unique hexadecimal address. The HT16K33 generally uses a 0x70 address, but we'll verify that later. The I<sup>2</sup>C bus uses only two GPIO pins:
The HT16K33 7-segment display uses the I<sup>2</sup>C bus. An I<sup>2</sup>C bus can support up to 256 different devices (e.g. sensors, motors, outputs) at the same time. Each component has a unique hexadecimal address. The HT16K33 generally uses a `0x70` address, but we'll verify that later. The I<sup>2</sup>C bus uses only two GPIO pins:

{{<figure title="The I<sup>2</sup>C bus lines">}}
Line | Purpose
@@ -59,7 +59,7 @@ The four-digit seven-segment display that we are going to use has 4 pins (+, -,
{{<figure title="The I<sup>2</sup>C bus lines">}}
7-Segment Pin | Purpose | GPIO Pin
--------------|---------|---------
+|Power|5.0V
+|Power|3.3V
-|Ground|GND
D|SDA (Data for I<sup>2</sup>C)|SDA
C|SCL (Clock for I<sup>2</sup>C)|SCL

0 comments on commit 8432248

Please sign in to comment.
You can’t perform that action at this time.