mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-22 19:36:49 +08:00
finished discussion of newly introduced instructions
This commit is contained in:
parent
fe34c2a9fd
commit
2614ef9ae4
2 changed files with 94 additions and 37 deletions
|
|
@ -12,8 +12,7 @@ Bit bashing is the manipulation of individual bits. Bit
|
||||||
bashing goes to the very core of the C language. Remember that C is a
|
bashing goes to the very core of the C language. Remember that C is a
|
||||||
high level assembly language, as we argue in Section 1 of this book.
|
high level assembly language, as we argue in Section 1 of this book.
|
||||||
And C is the (later) language in which Unix was implemented and indeed,
|
And C is the (later) language in which Unix was implemented and indeed,
|
||||||
C was
|
C was developed specifically to implement Unix.
|
||||||
developed specifically to implement Unix.
|
|
||||||
|
|
||||||
Since an operating system directly
|
Since an operating system directly
|
||||||
interfaces with hardware - the C language grew to have features
|
interfaces with hardware - the C language grew to have features
|
||||||
|
|
@ -45,7 +44,7 @@ Consider a data structure for which there will be potentially millions of
|
||||||
instances in RAM. Or, perhaps billions of instances on disc. Suppose you
|
instances in RAM. Or, perhaps billions of instances on disc. Suppose you
|
||||||
need 8 boolean members in every instance. The C++ standard does not
|
need 8 boolean members in every instance. The C++ standard does not
|
||||||
define the size of a `bool` instead leaving it to be implementation
|
define the size of a `bool` instead leaving it to be implementation
|
||||||
dependent. Some implementations equate `bool` to `int`, four bytes in
|
dependent. Some implementations equate `bool` to `int`, four bytes in
|
||||||
length. Some implement `bool` with a `char`, or 1 byte in length.
|
length. Some implement `bool` with a `char`, or 1 byte in length.
|
||||||
|
|
||||||
Let's assume the smallest case and equate a `bool` with `char`. Our
|
Let's assume the smallest case and equate a `bool` with `char`. Our
|
||||||
|
|
@ -250,7 +249,7 @@ Some might argue that instructions like `bfi` (and `ubfiz` described
|
||||||
below) is an example of `ISA creep` where ISA's get
|
below) is an example of `ISA creep` where ISA's get
|
||||||
more and more cumbersome with the latest instructions du jure. This is
|
more and more cumbersome with the latest instructions du jure. This is
|
||||||
definitely true in the x86 ISA. Perhaps this is true in the AARCH64 ISA
|
definitely true in the x86 ISA. Perhaps this is true in the AARCH64 ISA
|
||||||
as well, but certainly not to the extent of the x86.
|
as well, but certainly not to the extent of the x86.
|
||||||
|
|
||||||
Remember that the ARM
|
Remember that the ARM
|
||||||
family of processors are examples of RISC machines - *reduced instruction
|
family of processors are examples of RISC machines - *reduced instruction
|
||||||
|
|
@ -338,7 +337,7 @@ The remainder is as expected.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
In this chapter we saw was life was like without bit fields. We saw that
|
In this chapter we saw was life was like without bit fields. We saw that
|
||||||
we had to implement our own bit bashing functions to do things like:
|
we had to implement our own bit bashing functions to do things like:
|
||||||
|
|
||||||
* Ensure parameters are in the right range
|
* Ensure parameters are in the right range
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,19 @@
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Our discussion of implementing ourselves what the C / C++ compiler gives us
|
Our discussion of implementing ourselves what the C / C++ compiler gives
|
||||||
led us to use six new instructions. This chapter reviews those instructions.
|
us led us to use six new instructions. This chapter reviews those
|
||||||
|
instructions. In addition to describing what an instruction does, we
|
||||||
|
will try to indicate what the instruction is "good for."
|
||||||
|
|
||||||
## `and`
|
## `and`
|
||||||
|
|
||||||
The `and` instruction is pretty much what you would expect. It implements
|
The `and` instruction is pretty much what you would expect. It
|
||||||
the `&` operator from C and C++. That is, the bitwise and operator.
|
implements the `&` operator from C and C++. That is, the bitwise and
|
||||||
|
operator.
|
||||||
|
|
||||||
The `and` instruction comes in a number of flavors
|
The `and` instruction comes in a number of flavors including for
|
||||||
|
use with immediate values.
|
||||||
|
|
||||||
### `and` Immediate
|
### `and` Immediate
|
||||||
|
|
||||||
|
|
@ -27,20 +31,19 @@ There are limits to the bit width of `imm` because it has to fit within
|
||||||
the `and` instruction. If you exceed the allowable width of `imm`, the
|
the `and` instruction. If you exceed the allowable width of `imm`, the
|
||||||
assembler will be glad to insult you.
|
assembler will be glad to insult you.
|
||||||
|
|
||||||
It is possible that a `mov`
|
It is possible that a `mov` instruction will allow your immediate value.
|
||||||
instruction will allow your immediate value. You'd follow up with an
|
You'd follow up with an `and` using a register than an immediate value.
|
||||||
`and` using a register than an immediate value.
|
|
||||||
|
|
||||||
If your immediate value is too large for a `mov` then put the value
|
If your immediate value is too large for a `mov` then put the value in
|
||||||
in RAM and `ldr` it into a register and proceed.
|
RAM and `ldr` it into a register and proceed.
|
||||||
|
|
||||||
We would love to tell you what the rules are for an immediate value in
|
We would love to tell you what the rules are for an immediate value in
|
||||||
the `and` instruction, but they are not obvious and in fact are very
|
the `and` instruction, but they are not obvious and in fact are very
|
||||||
complex. Our advice, try the immediate value you have in mind and if
|
complex. Our advice, try the immediate value you have in mind and if it
|
||||||
it works, great. Otherwise, see above.
|
works, great. Otherwise, see above.
|
||||||
|
|
||||||
A slight variation on this `and` instruction uses a register where
|
A slight variation on this `and` instruction uses a register where the
|
||||||
the preceding one uses an immediate value.
|
preceding one uses an immediate value.
|
||||||
|
|
||||||
```asm
|
```asm
|
||||||
and rd, rs, rm
|
and rd, rs, rm
|
||||||
|
|
@ -65,18 +68,29 @@ These mean:
|
||||||
| `asr` | arithmetic shift right | shifts right introducing duplicates of the previous most significant bit |
|
| `asr` | arithmetic shift right | shifts right introducing duplicates of the previous most significant bit |
|
||||||
| `ror` | rotate right | shifts right introducing the bits shifted out back in from the left |
|
| `ror` | rotate right | shifts right introducing the bits shifted out back in from the left |
|
||||||
|
|
||||||
There are other two similar `and` instructions. These are the immediate and
|
There are other two similar `and` instructions. These are the immediate
|
||||||
the register versions of `ands`. `ands` is the same as `and` with the addition
|
and the register versions of `ands`. `ands` is the same as `and` with
|
||||||
that the CPU's condition bits are updated by the instruction permitting a
|
the addition that the CPU's condition bits are updated by the
|
||||||
conditional branch to follow the instruction.
|
instruction permitting a conditional branch to follow the instruction.
|
||||||
|
|
||||||
|
*`and` is the basis of bit bashing and is used to clear bits.
|
||||||
|
Put `and` together with the or instructions and a couple of other basic
|
||||||
|
logic instructions, out pops a computer.*
|
||||||
|
|
||||||
|
A shorthand way of clearing specific bits is the `bic` instruction.
|
||||||
|
Use of `bic` can avoid having to negate the bits in a mask prior to
|
||||||
|
and'ing.
|
||||||
|
|
||||||
## `bfi`
|
## `bfi`
|
||||||
|
|
||||||
This instruction mnemonic stands for Bit Field Insert. The word *Insert* should
|
This instruction mnemonic stands for Bit Field Insert. The word *Insert*
|
||||||
really be copy. The official ARM [documentation](https://developer.arm.com/documentation/dui0801/g/A64-General-Instructions/BFI) explains this instruction
|
should really be copy. The official ARM
|
||||||
very well so we'll repeat it here:
|
[documentation](https://developer.arm.com/documentation/dui0801/g/A64-General-Instructions/BFI)
|
||||||
|
explains this instruction very well so we'll repeat it here:
|
||||||
|
|
||||||
*Bit Field Insert copies any number of low-order bits from a source register into the same number of adjacent bits at any position in the destination register, leaving other bits unchanged.*
|
*Bit Field Insert copies any number of low-order bits from a source
|
||||||
|
register into the same number of adjacent bits at any position in the
|
||||||
|
destination register, leaving other bits unchanged.*
|
||||||
|
|
||||||
The instruction has the following format:
|
The instruction has the following format:
|
||||||
|
|
||||||
|
|
@ -84,16 +98,29 @@ The instruction has the following format:
|
||||||
bfi rd, rs, lsb, width
|
bfi rd, rs, lsb, width
|
||||||
```
|
```
|
||||||
|
|
||||||
Starting at bit 0 of `rs`, `width` bits are copied to `rd` starting at bit
|
Starting at bit 0 of `rs`, `width` bits are copied to `rd` starting at
|
||||||
`lsb`.
|
bit `lsb`.
|
||||||
|
|
||||||
The `bfi` instruction replaces as many as three instructions: likely a shift,
|
The `bfi` instruction replaces as many as three instructions: likely a
|
||||||
an `and` and an `orr`.
|
shift, an `and` and an `orr`.
|
||||||
|
|
||||||
|
*The preceding has described what `bfi` does but what is it for? Suppose
|
||||||
|
you have a multiple bit field in a device register. Using `bfi` makes
|
||||||
|
it easy to copy the right number of bits from a source directly into
|
||||||
|
the bits in the middle of the destination without need of other
|
||||||
|
bit-bashing.*
|
||||||
|
|
||||||
|
The *opposite* of `bfi` is `bfx`.
|
||||||
|
|
||||||
|
`ubfiz` first zeros the destination register then copies in the
|
||||||
|
specified bits from the source. The `u` means don't consider the
|
||||||
|
sign bit as special. The `z` is what causes the zero fill first and
|
||||||
|
sets it apart from `bfi`.
|
||||||
|
|
||||||
## `mvn`
|
## `mvn`
|
||||||
|
|
||||||
This instruction takes only takes two operands (but permits an optional shift
|
This instruction takes only takes two operands (but permits an optional
|
||||||
to be explained below).
|
shift to be explained below).
|
||||||
|
|
||||||
The basic syntax is:
|
The basic syntax is:
|
||||||
|
|
||||||
|
|
@ -101,7 +128,8 @@ The basic syntax is:
|
||||||
mvn rd, rs
|
mvn rd, rs
|
||||||
```
|
```
|
||||||
|
|
||||||
This flips all the bits in the source and copies them to the destination.
|
This flips all the bits in the source and copies them to the
|
||||||
|
destination.
|
||||||
|
|
||||||
In addition to the basic instruction, there is also:
|
In addition to the basic instruction, there is also:
|
||||||
|
|
||||||
|
|
@ -109,11 +137,41 @@ In addition to the basic instruction, there is also:
|
||||||
mvn rd, rs, *shift* num_bits
|
mvn rd, rs, *shift* num_bits
|
||||||
```
|
```
|
||||||
|
|
||||||
The *shift* and `num_bits` function the same way as described above including
|
The *shift* and `num_bits` function the same way as described above
|
||||||
the option to use `*shift*` as one of `lsl`, `lsr`, `asr` or `ror`.
|
including the option to use `*shift*` as one of `lsl`, `lsr`, `asr` or
|
||||||
|
`ror`.
|
||||||
|
|
||||||
|
*Note the `mvn` is different from `neg` in that `mvn` is a bitwise
|
||||||
|
operation while `neg` is aware of what makes a negative integer value.
|
||||||
|
That is, if your goal is to turn a positive integer into a negative
|
||||||
|
integer, use `neg`. If your goal is to negate bits for bit bashing
|
||||||
|
purposes, use `mvn`.*
|
||||||
|
|
||||||
## `lsl`
|
## `lsl`
|
||||||
|
|
||||||
|
**Logical Shift Left** moves bits to the left shifting 0 into any
|
||||||
|
vacated positions.
|
||||||
|
|
||||||
|
```asm
|
||||||
|
lsl rd, rs, *number of bits*
|
||||||
|
```
|
||||||
|
|
||||||
|
*`lsl` is most often used for bit bashing as well as for a fast
|
||||||
|
multiplication by a power of 2.*
|
||||||
|
|
||||||
|
The instruction `asl` is a synonym for `lsl`. The `a` is `asl` means
|
||||||
|
"arithmetic". There is no difference between a logical and
|
||||||
|
an arithmetic shift in the **leftward** direction. There is, however,
|
||||||
|
a difference in the **rightward** direction in that `asr` replicates
|
||||||
|
the sign bit where `lsr` still moves in zeros in any bit positions
|
||||||
|
vacated.
|
||||||
|
|
||||||
## `orr`
|
## `orr`
|
||||||
|
|
||||||
## `ubfiz`
|
This is the plain vanilla *or* instruction. It is used extensively
|
||||||
|
for bit bashing as it is how bits can be set to 1.
|
||||||
|
|
||||||
|
```asm
|
||||||
|
orr rd, rs, rm # rm is another register
|
||||||
|
orr rd, rs, imm
|
||||||
|
```
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue