pete > courses > CS 202 Spring 24 > Lecture 15: mov, immediate values, and value extension
Lecture 15: mov, immediate values, and value extension
Goals
- explain the effect of the move immediate instruction
- define immediate value and explain its utility
- perform sign extension, zero extension, and rotation
pop quiz!
what is -3 in 4-bit two’s complement?
1101
what about the same value in 8-bit two’s complement?
1111 1101
16-bit?
1111 1111 1111 1101
what’s the pattern?
if we want to increase the number of bits but retain the same value, fill with ones to the left
we’ll return to this in a bit
before we get back into specific ARM32 instructions, I have a confession
in the name of simplifying things for the scope of the course, I claimed that a certain collection of bits (23-27) in the instruction was the opcode—the bits that identify what operation the instruction performs
it’s a bit more complicated than that, and since we’re going to see some of that complication today, I figured why not inflict it all on you
here is the reference for ARM32’s add instruction, which we looked at last time:
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|0|0 1 0 0|S| Rn | Rd | | Rm | +---------------------------------------------------------------+ assembly: add Rd, Rn, Rm effect: Rd <- Rn + Rm example: e0823003 add r3, r2, r3
I have filled in more bits and added more separators
ARM32 divides its various instructions into categories, one of which is "data processing", of which the add instruction is a member
the instruction category is identified by bits 26-27: 0 0 means "data processing"
I will defer the meaning of bit 25 for a few minutes
bits 21-24 identify the particular data processing operation; in this case, add
now, here’s a reference for ARM32’s subtract instruction, sub:
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|0|0 0 1 0|S| Rn | Rd | | Rm | +---------------------------------------------------------------+ assembly: sub Rd, Rn, Rm effect: Rd <- Rn - Rm example: e0423003 sub r3, r2, r3
first, the differences:
- bits 21-24 are now 0 0 1 0, which is the sequence of bits that identifies the subtraction operation
- the mnemonic is "sub" (unsurprising)
- the arithmetic operation being performed is subtraction (even less surprising)
there are a couple similarities worth noting:
- this instruction is also exactly 32 bits long (recall that, in RISC instruction sets, instructions are usually all the same length)
- the source registers and destination registers are specified using the same bits of the instruction as in the add instruction (this is very intentionally to simplify wiring!)
this latter point is, in fact, going to hold for all arithmetic and logical operations that involve two operands
so a multiplication instruction, or a division instruction, or an instruction that performs XOR will use the same bits of the instruction to specify sources and destination
what about an instruction that only has one operand?
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|0|1 1 0 1|S| | Rd | | Rm | +---------------------------------------------------------------+ assembly: mov Rd, Rm effect: Rd <- Rm example: e1a00003 mov r0, r3
the "move" instruction takes a value from one register and puts it into another register
it’s a bit misleadingly-named, though, because the value in the source register isn’t modified
it might be more appropriate to think of the operation as "copy" instead of "move", but the name "move" has been used for this for decades, so it’s what we’re stuck with
we still haven’t addressed the problem we noted at the end of last lecture, however
namely, that it’s nice to be able to add the contents of registers (and now subtract or move them) but how do we actually get an interesting value into a register to begin with?
adding, subtracting, or moving the contents of registers that contain all zeroes doesn’t give us anything except more zeroes
therefore, I present to you the "move immediate" instruction:
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|1|1 1 0 1|S| | Rd | imm12 | +---------------------------------------------------------------+ assembly: mov Rd, #imm12 effect: Rd <- extend(imm12) example: e3a0300a mov r3, #10
this is an interesting one: there is no source register!
and yet we would assume (correctly!) that it has a similar effect to the mov instruction we just looked at: it puts a value in a register
this instruction uses an immediate value, however: an operand that comes, not from a register (nor from memory, which will we see soon), but from the bits of the instruction itself
so the result of this instruction is that the low 12 bits of the instruction (bits 0-11) are copied into Rd
there’s one problem, though: this is ARM32, so the registers each store 32 bits, but the immediate value here is only 12 bits
what do we do with the other 20 bits?
here’s one line of reasoning:
we might want to store either positive or negative numbers in registers
two’s complement is the natural choice (and indeed how ARM32 represents signed integers)
let’s assume we want to put our 12-bit immediate value into the 32-bit register and have it retain the same meaning
if the immediate value is 0000 0000 0011 (the 12-bit representation of 3), then, after the instruction executes, we would like the register to contain 0000 0000 0000 0000 0000 0000 0000 0011 (the 32-bit representation of 3)
if the immediate value is 1111 1111 1101 (the 12-bit representation of -3), then, after the instruction executes, we would like the register to contain 1111 1111 1111 1111 1111 1111 1111 1101 (the 32-bit representation of -3, following the pattern from the beginning of today’s discussion)
in both cases, we put the 12-bit immediate value in the low 12 bits of the register
in the case of a non-negative number, we fill the high 20 bits with zeroes
in the case of a negative number, we will the high 20 bits with ones
recall, though, that the most-significant bit of a non-negative number will always be zero and the most-significant bit of a negative number will always be one
this matches the bit we’re using to fill the high 20 bits!
we can refer to the most-significant bit of a two’s complement number as the sign bit
so, no matter whether the value is positive or negative, we take the 12-bit value and extend (copy) the sign bit to fill all the more significant bits of the larger space
this is a process called sign extension
an alternative to sign extension is zero extension, where we fill the more significant bits with zeroes
we will see uses of both
and you might be tempted to assume that we will see one of them used for the 12-bit immediate value in the move immediate instruction
but you would be wrong!
the move immediate instruction uses a different (more complicated) method
I presented zero-extension and sign-extension first, with no intention of actually making use of either today, because a) they’re simpler and b) you need to know them
so what does move immediate do?
the 12-bit immediate value is actually broken down into two parts: a rotation and a value:
1 0 1 0 9 8 7 6 5 4 3 2 1 0 +-----------------------+ | rot | value | +-----------------------+
the value is the actual bits that get stored in the register
the rotation is an operation we perform on the bits before they arrive in the register
here’s the process:
- zero-extend the 8-bit value to 32 bits
- interpret the 4-bit rot value as an unsigned integer
- multiply the rot value by 2
- shift the bits of the 32-bit value to right by "rot * 2"; any bits that fall off the right are added onto the left
(this operation, wherein we shift and any bits that fall off are tacked onto the other end, is called rotation)
example the first (in which "abcdefgh" represent arbitrary bits, a trick I stole directly from the official ARM32 documentation):
0001 abcdefgh
we first zero-extend the 8-bit value to 32 bits:
0000 0000 0000 0000 0000 0000 abcd efgh
then we interpret the rotation as an unsigned integer: 1
we multiply it by 2: 2
then we rotate by that many spots:
gh00 0000 0000 0000 0000 0000 00ab cdef
example the second, this time with less commentary:
imm12:
0101 abcdefgh
zero-extend:
0000 0000 0000 0000 0000 0000 abcd efgh
rotate by 5 * 2 = 10:
00ab cdef gh00 0000 0000 0000 0000 0000
there are variants of the add and sub instructions that also take an immediate value as the second operand:
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|1|0 1 0 0|S| Rn | Rd | imm12 | +---------------------------------------------------------------+ assembly: add Rd, Rn, #imm12 effect: Rd <- Rn + extend(imm12) example: e283300a add r3, r3, #10
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|1|0 0 1 0|S| Rn | Rd | imm12 | +---------------------------------------------------------------+ assembly: sub Rd, Rn, #imm12 effect: Rd <- Rn - extend(imm12) example: e243300a sub r3, r3, #10
we call these "add immediate" and "sub immediate", respectively
note that the opcodes are the same as in the "add register" and "sub register" instructions we looked at earlier
the difference is in bit 25: this is the bit that specifies whether we are using an immediate value or not
the sub immediate instruction allows us to subtract an immediate value from the contents of a register
but what about the opposite: subtract the contents of a register from an immediate value?
we need a different instruction: reverse subtract (rsb)
3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | |0 0|1|0 0 1 1|S| Rn | Rd | imm12 | +---------------------------------------------------------------+ assembly: rsb Rd, Rn, #imm12 effect: Rd <- extend(imm12) - Rn example: e263300a rsb r3, r3, #10
Definitions
The following definitions introduced in this lecture are fair-game for future quizzes. You will be expected to give the exact definition as provided in these lecture notes.
- immediate value
Mechanical Skills
The following mechanical skills introduced in this lecture are fair-game for future quizzes. You may access practice questions (which will exactly resemble the questions on the quizzes) on weathertop.
t1p2m02 assemble/disassemble data-processing instructions (immediate)