mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 02:06:48 +08:00
typo found by Katie
This commit is contained in:
parent
8382853043
commit
e7a99b1072
3 changed files with 104 additions and 63 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -49,6 +49,7 @@
|
|||
"Rypo",
|
||||
"SIZD",
|
||||
"SIZF",
|
||||
"amining",
|
||||
"bitfields",
|
||||
"dless",
|
||||
"dmore",
|
||||
|
|
@ -56,12 +57,14 @@
|
|||
"fcvtps",
|
||||
"fcvtta",
|
||||
"foov",
|
||||
"iant",
|
||||
"ndless",
|
||||
"ndmore",
|
||||
"nvless",
|
||||
"nvmore",
|
||||
"onditionally",
|
||||
"onsole",
|
||||
"rint",
|
||||
"rotypo",
|
||||
"rwtypo",
|
||||
"slen",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
## Overview
|
||||
|
||||
In each of the various sets of registers, each register can be referred to by different synonyms which determine how wide the register operation will be.
|
||||
In each of the various sets of registers, each register can be referred
|
||||
to by different synonyms which determine how wide the register operation
|
||||
will be.
|
||||
|
||||
## General Purpose Registers
|
||||
|
||||
|
|
@ -22,7 +24,13 @@ In each of the various sets of registers, each register can be referred to by di
|
|||
ldrb w0, [sp] // load 1 byte from address specified by sp
|
||||
```
|
||||
|
||||
The address from which a load is taking must match the alignment of what is being loaded.
|
||||
The address from which a load is taking *should* match the alignment of
|
||||
what is being loaded. That is, a long *should* be found only at
|
||||
addresses which are a multiple of 8 (the size of a long).
|
||||
|
||||
**When misaligned accesses to RAM are made, the processor must slow down
|
||||
and access each byte individually. This is a big performance hit.
|
||||
Properly aligned access is critical to performance.**
|
||||
|
||||
### `str` (and `stp`)
|
||||
|
||||
|
|
@ -33,30 +41,30 @@ The address from which a load is taking must match the alignment of what is bein
|
|||
strb w0, [sp] // store 1 byte to address specified by sp
|
||||
```
|
||||
|
||||
The address to which a store is made must match the alignment of what is being stored.
|
||||
See above for comments about misaligned memory access.
|
||||
|
||||
### Example
|
||||
|
||||
Let's look at this program:
|
||||
|
||||
```asm
|
||||
.global main // 1
|
||||
.text // 2
|
||||
.align 2 // 3
|
||||
// 4
|
||||
main: mov x0, xzr // 5
|
||||
ldr x1, =ram // 6
|
||||
strb w0, [x1] // 7
|
||||
strh w0, [x1] // 8
|
||||
str w0, [x1] // 9
|
||||
str x0, [x1] // 10
|
||||
ret // 11
|
||||
// 12
|
||||
.data // 13
|
||||
ram: .quad 0xFFFFFFFFFFFFFFFF // 14
|
||||
// 15
|
||||
.end // 16
|
||||
// 17
|
||||
.global main // 1
|
||||
.text // 2
|
||||
.align 2 // 3
|
||||
// 4
|
||||
main: mov x0, xzr // 5
|
||||
ldr x1, =ram // 6
|
||||
strb w0, [x1] // 7
|
||||
strh w0, [x1] // 8
|
||||
str w0, [x1] // 9
|
||||
str x0, [x1] // 10
|
||||
ret // 11
|
||||
// 12
|
||||
.data // 13
|
||||
ram: .quad 0xFFFFFFFFFFFFFFFF // 14
|
||||
// 15
|
||||
.end // 16
|
||||
// 17
|
||||
```
|
||||
|
||||
`Line 14` puts an identifiable pattern into 8 bytes of RAM and gives them the symbol `ram`.
|
||||
|
|
@ -82,14 +90,18 @@ Breakpoint 1, main () at align.s:5 // 6
|
|||
5 main: mov x0, xzr // 7
|
||||
```
|
||||
|
||||
We launched the program and `gdb` stops its execution upon reaching the breakpoint.
|
||||
We launched the program and `gdb` stops its execution upon reaching the
|
||||
breakpoint.
|
||||
|
||||
```text
|
||||
(gdb) p/x $x0 // 8
|
||||
$1 = 0x1 // 9
|
||||
```
|
||||
|
||||
Before putting zero into `x0`, let's see what it currently holds... the value 1. Recall this is `argc`. The `p` command means `print` and is used to print the values in registers. The modifier `/x` says to print in hexadecimal.
|
||||
Before putting zero into `x0`, let's see what it currently holds... the
|
||||
value 1. Recall this is `argc`. The `p` command means `print` and is
|
||||
used to print the values in registers. The modifier `/x` says to print
|
||||
in hexadecimal.
|
||||
|
||||
```text
|
||||
(gdb) n // 10
|
||||
|
|
@ -105,85 +117,98 @@ After putting zero into `x0`, we confirm its contents.
|
|||
$3 = 0xfffffffff028 // 15
|
||||
```
|
||||
|
||||
Prior to loading the address of 8 bytes found with the label `ram`, we print out the value already sitting in `x1`. The address it contains will be the address of the `C`-string containing the name of the program being run.
|
||||
Prior to loading the address of 8 bytes found with the label `ram`, we
|
||||
print out the value already sitting in `x1`. The address it contains
|
||||
will be the address of the `C`-string containing the name of the program
|
||||
being run. Notice this value is 6-bytes long and not 8 as we might have
|
||||
expected. Why? The answer relates to the size of the virtual address
|
||||
each program is allowed. A full 64-bit virtual address space would make
|
||||
certain OS data structures too large for efficiency.
|
||||
|
||||
```text
|
||||
(gdb) n // 16
|
||||
7 strb w0, [x1] // 17
|
||||
(gdb) p/x $x1 // 18
|
||||
$4 = 0xaaaaaaab1010 // 19
|
||||
(gdb) n // 16
|
||||
7 strb w0, [x1] // 17
|
||||
(gdb) p/x $x1 // 18
|
||||
$4 = 0xaaaaaaab1010 // 19
|
||||
```
|
||||
|
||||
After loading the address of `ram` into `x1`, we confirm its contents.
|
||||
|
||||
```text
|
||||
(gdb) p/x &ram // 20
|
||||
$5 = 0xaaaaaaab1010 // 21
|
||||
(gdb) p/x &ram // 20
|
||||
$5 = 0xaaaaaaab1010 // 21
|
||||
```
|
||||
|
||||
Just for kicks, we confirm that the previous instruction really did get the address correctly.
|
||||
Just for kicks, we confirm that the previous instruction really did get
|
||||
the address correctly.
|
||||
|
||||
```text
|
||||
(gdb) x/x &ram // 22
|
||||
0xaaaaaaab1010: 0xffffffff // 23
|
||||
(gdb) x/x &ram // 22
|
||||
0xaaaaaaab1010: 0xffffffff // 23
|
||||
```
|
||||
|
||||
We shift from `p`rint to e`x`amine to reach into memory and see what is found at `ram`.
|
||||
We shift from `p`rint to e`x`amine to reach into memory and see what is
|
||||
found at `ram`.
|
||||
|
||||
```text
|
||||
(gdb) x/gx &ram // 24
|
||||
0xaaaaaaab1010: 0xffffffffffffffff // 25
|
||||
(gdb) x/gx &ram // 24
|
||||
0xaaaaaaab1010: 0xffffffffffffffff // 25
|
||||
```
|
||||
|
||||
Adding the `g` (for `g`iant) we can see all 8 bytes.
|
||||
|
||||
```text
|
||||
(gdb) n // 26
|
||||
8 strh w0, [x1] // 27
|
||||
(gdb) x/gx &ram // 28
|
||||
0xaaaaaaab1010: 0xffffffffffffff00 // 29
|
||||
(gdb) n // 26
|
||||
8 strh w0, [x1] // 27
|
||||
(gdb) x/gx &ram // 28
|
||||
0xaaaaaaab1010: 0xffffffffffffff00 // 29
|
||||
```
|
||||
|
||||
We just did a `strb` and looking at memory, we see one byte's worth of zeros.
|
||||
|
||||
*Note: this brings up an interesting question... which byte is actually sitting at the address of `ram`? We will have to look into this more later.*
|
||||
*Note: this brings up an interesting question... which byte is actually
|
||||
sitting at the address of `ram`? We will have to look into this more
|
||||
later.*
|
||||
|
||||
```text
|
||||
(gdb) n // 30
|
||||
9 str w0, [x1] // 31
|
||||
(gdb) x/gx &ram // 32
|
||||
0xaaaaaaab1010: 0xffffffffffff0000 // 33
|
||||
(gdb) n // 30
|
||||
9 str w0, [x1] // 31
|
||||
(gdb) x/gx &ram // 32
|
||||
0xaaaaaaab1010: 0xffffffffffff0000 // 33
|
||||
```
|
||||
|
||||
After storing a `short`.
|
||||
|
||||
```text
|
||||
(gdb) n // 34
|
||||
10 str x0, [x1] // 35
|
||||
(gdb) x/gx &ram // 36
|
||||
0xaaaaaaab1010: 0xffffffff00000000 // 37
|
||||
(gdb) n // 34
|
||||
10 str x0, [x1] // 35
|
||||
(gdb) x/gx &ram // 36
|
||||
0xaaaaaaab1010: 0xffffffff00000000 // 37
|
||||
```
|
||||
|
||||
After storing an `int`.
|
||||
|
||||
```text
|
||||
(gdb) n // 38
|
||||
11 ret // 39
|
||||
(gdb) x/gx &ram // 40
|
||||
0xaaaaaaab1010: 0x0000000000000000 // 41
|
||||
(gdb) quit // 42
|
||||
(gdb) n // 38
|
||||
11 ret // 39
|
||||
(gdb) x/gx &ram // 40
|
||||
0xaaaaaaab1010: 0x0000000000000000 // 41
|
||||
(gdb) quit // 42
|
||||
```
|
||||
|
||||
And finally, after storing a `long`.
|
||||
|
||||
Let's circle back to the question asked above: Which byte is actually at the address `ram`? When we examined the `long` just after putting in one byte of zero, we saw this:
|
||||
Let's circle back to the question asked above: Which byte is actually at
|
||||
the address `ram`? When we examined the `long` just after putting in one
|
||||
byte of zero, we saw this:
|
||||
|
||||
```text
|
||||
(gdb) x/gx &ram // 28
|
||||
0xaaaaaaab1010: 0xffffffffffffff00 // 29
|
||||
```
|
||||
|
||||
Notice the zeros come at the end. Keep in mind, these bytes are printed as a `long`.
|
||||
Notice the zeros come at the end. Keep in mind, these bytes are printed
|
||||
as a `long`.
|
||||
|
||||
But what if we look at these 8 bytes individually?
|
||||
|
||||
|
|
@ -204,7 +229,8 @@ The following image is from [here](https://medium.com/worldsensing-techblog/big-
|
|||
|
||||
### Little Endian in More Detail
|
||||
|
||||
Given this program (not intended for meaningful execution... just e`x`aminging memory):
|
||||
Given this program (not intended for meaningful execution... just
|
||||
e`x`amining memory):
|
||||
|
||||
```asm
|
||||
.global main // 1
|
||||
|
|
@ -219,34 +245,46 @@ ram: .quad 0xAABBCCDDEEFF0011 // 9
|
|||
.end // 10
|
||||
```
|
||||
|
||||
let's take a look at the memory at location `ram` in two ways. Once interpreted as a `long`:
|
||||
let's take a look at the memory at location `ram` in two ways. Once
|
||||
interpreted as a `long`:
|
||||
|
||||
```text
|
||||
(gdb) x/gx &ram
|
||||
0x11010: 0xaabbccddeeff0011
|
||||
```
|
||||
|
||||
and then intrepreted as 8 bytes appearing in the order of lowest address to highest:
|
||||
and then interpreted as 8 bytes appearing in the order of lowest address
|
||||
to highest:
|
||||
|
||||
```text
|
||||
(gdb) x/8bx &ram
|
||||
0x11010: 0x11 0x00 0xff 0xee 0xdd 0xcc 0xbb 0xaa
|
||||
```
|
||||
|
||||
Compare the order of the bytes. They are least significant to most significant. Specifically:
|
||||
Compare the order of the bytes. They are least significant to most
|
||||
significant. Specifically:
|
||||
|
||||
* within a `long` the least significant `int` comes first
|
||||
* within an `int`, the least significant `short` comes first
|
||||
* within a `short` the least significant byte comes first
|
||||
|
||||
Endiannes isn't an issue unless you're exchanging data with a computer that has a different endedness and then only if the data being transferred is longer in native width than 1 byte. Text, expressed in single bytes, is immune from endedness issues - text is an array of bytes and is the same on all platforms.
|
||||
Endiannes isn't an issue unless you're exchanging data with a computer
|
||||
that has a different endedness and then only if the data being
|
||||
transferred is longer in native width than 1 byte. Text, expressed in
|
||||
single bytes, is immune from endedness issues - text is an array of
|
||||
bytes and is the same on all platforms.
|
||||
|
||||
### What Happens to the Rest of a Register When Only a Portion is Affected?
|
||||
|
||||
Whenever a narrower portion of a register is written to, the remainder of the registe is zero'd out. That is: `strb` overwrites the least significant byte of an `x` register and zeros out the upper 7 bytes.
|
||||
Whenever a narrower portion of a register is written to, the remainder
|
||||
of the register is zero'd out. That is: `ldrb` overwrites the least
|
||||
significant byte of an `x` register and zeros out the upper 7 bytes.
|
||||
|
||||
*There are dedicated instructions for manipulating bits in the middle of registers*.
|
||||
*There are dedicated instructions for manipulating bits in the middle of
|
||||
registers*.
|
||||
|
||||
### Casting Between `int` Type
|
||||
|
||||
Casting between integer types is in some cases accomplished by `anding` with `255` and `65535` (for `char` and `short`). Otherwise, see the previous section (What Happens to the Rest of a Register...).
|
||||
Casting between integer types is in some cases accomplished by `anding`
|
||||
with `255` and `65535` (for `char` and `short`). Otherwise, see the
|
||||
previous section (What Happens to the Rest of a Register...).
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in a new issue