mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 05:16:46 +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
|
||||
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,
|
||||
C was
|
||||
developed specifically to implement Unix.
|
||||
C was developed specifically to implement Unix.
|
||||
|
||||
Since an operating system directly
|
||||
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
|
||||
need 8 boolean members in every instance. The C++ standard does not
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
family of processors are examples of RISC machines - *reduced instruction
|
||||
|
|
@ -338,7 +337,7 @@ The remainder is as expected.
|
|||
|
||||
## 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:
|
||||
|
||||
* Ensure parameters are in the right range
|
||||
|
|
|
|||
|
|
@ -2,15 +2,19 @@
|
|||
|
||||
## Overview
|
||||
|
||||
Our discussion of implementing ourselves what the C / C++ compiler gives us
|
||||
led us to use six new instructions. This chapter reviews those instructions.
|
||||
Our discussion of implementing ourselves what the C / C++ compiler gives
|
||||
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`
|
||||
|
||||
The `and` instruction is pretty much what you would expect. It implements
|
||||
the `&` operator from C and C++. That is, the bitwise and operator.
|
||||
The `and` instruction is pretty much what you would expect. It
|
||||
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
|
||||
|
||||
|
|
@ -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
|
||||
assembler will be glad to insult you.
|
||||
|
||||
It is possible that a `mov`
|
||||
instruction will allow your immediate value. You'd follow up with an
|
||||
`and` using a register than an immediate value.
|
||||
It is possible that a `mov` instruction will allow your immediate value.
|
||||
You'd follow up with an `and` using a register than an immediate value.
|
||||
|
||||
If your immediate value is too large for a `mov` then put the value
|
||||
in RAM and `ldr` it into a register and proceed.
|
||||
If your immediate value is too large for a `mov` then put the value in
|
||||
RAM and `ldr` it into a register and proceed.
|
||||
|
||||
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
|
||||
complex. Our advice, try the immediate value you have in mind and if
|
||||
it works, great. Otherwise, see above.
|
||||
complex. Our advice, try the immediate value you have in mind and if it
|
||||
works, great. Otherwise, see above.
|
||||
|
||||
A slight variation on this `and` instruction uses a register where
|
||||
the preceding one uses an immediate value.
|
||||
A slight variation on this `and` instruction uses a register where the
|
||||
preceding one uses an immediate value.
|
||||
|
||||
```asm
|
||||
and rd, rs, rm
|
||||
|
|
@ -65,18 +68,29 @@ These mean:
|
|||
| `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 |
|
||||
|
||||
There are other two similar `and` instructions. These are the immediate and
|
||||
the register versions of `ands`. `ands` is the same as `and` with the addition
|
||||
that the CPU's condition bits are updated by the instruction permitting a
|
||||
conditional branch to follow the instruction.
|
||||
There are other two similar `and` instructions. These are the immediate
|
||||
and the register versions of `ands`. `ands` is the same as `and` with
|
||||
the addition that the CPU's condition bits are updated by the
|
||||
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`
|
||||
|
||||
This instruction mnemonic stands for Bit Field Insert. The word *Insert* should
|
||||
really be copy. The official ARM [documentation](https://developer.arm.com/documentation/dui0801/g/A64-General-Instructions/BFI) explains this instruction
|
||||
very well so we'll repeat it here:
|
||||
This instruction mnemonic stands for Bit Field Insert. The word *Insert*
|
||||
should really be copy. The official ARM
|
||||
[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:
|
||||
|
||||
|
|
@ -84,16 +98,29 @@ The instruction has the following format:
|
|||
bfi rd, rs, lsb, width
|
||||
```
|
||||
|
||||
Starting at bit 0 of `rs`, `width` bits are copied to `rd` starting at bit
|
||||
`lsb`.
|
||||
Starting at bit 0 of `rs`, `width` bits are copied to `rd` starting at
|
||||
bit `lsb`.
|
||||
|
||||
The `bfi` instruction replaces as many as three instructions: likely a shift,
|
||||
an `and` and an `orr`.
|
||||
The `bfi` instruction replaces as many as three instructions: likely a
|
||||
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`
|
||||
|
||||
This instruction takes only takes two operands (but permits an optional shift
|
||||
to be explained below).
|
||||
This instruction takes only takes two operands (but permits an optional
|
||||
shift to be explained below).
|
||||
|
||||
The basic syntax is:
|
||||
|
||||
|
|
@ -101,7 +128,8 @@ The basic syntax is:
|
|||
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:
|
||||
|
||||
|
|
@ -109,11 +137,41 @@ In addition to the basic instruction, there is also:
|
|||
mvn rd, rs, *shift* num_bits
|
||||
```
|
||||
|
||||
The *shift* and `num_bits` function the same way as described above including
|
||||
the option to use `*shift*` as one of `lsl`, `lsr`, `asr` or `ror`.
|
||||
The *shift* and `num_bits` function the same way as described above
|
||||
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`
|
||||
|
||||
**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`
|
||||
|
||||
## `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