Left bit shift Created 2026-10-20 Updated 2026-10-24
A bit shift toward more significant positions, filling low positions with zeros. On an unbounded nonnegative integer, shifting left by places multiplies it by ; fixed-width representations may discard overflowing high bits.
Paging 2026-10-13
Paging divides an address space into fixed-size memory pages and main computer memory into equally sized page frames. Here assume byte addressing, one memory page size bytes, and an unsigned virtual address . Its virtual page number and offset are
The brackets denote the floor function, and gives the remainder in Euclidean division. If the page table maps to physical frame number and permits the access, the physical address is
The low bits are unchanged; the other bits select the memory page or page frame. A bit shift and bit mask can extract these fields. [ref]
For a 16-bit virtual address and bytes, take in hexadecimal. Then and . A mapping to gives
Thus the eight high bits choose a mapping; the eight low bits choose the same position in the resulting page frame. The 256-byte size is for illustration, not a claim about an actual architecture's supported memory page sizes.
Figure 1.
Translating 0x1234 through an illustrative page table, with a separate offset and access check
. Details.
The useful freedom is that adjacent memory pages can occupy unrelated page frames. In the diagram, virtual pages 0x12 and 0x13 occupy page frames 0x07 and 0x02; virtual addresses 0x12ff and 0x1300 are consecutive, but translate to physical addresses 0x07ff and 0x0200. Uniform units simplify placement and page replacement, at the cost of page table storage and unused bytes within partly filled memory pages. For example, placing 300 bytes in exclusive 256-byte page frames requires two page frames, leaving bytes unused.
Choose bit zero of each integer to represent the leftmost cell in its group of 32 columns. Then use a quotient to choose the word and a remainder to choose the bit:
java
static boolean getBit(int[][] board, int i, int j) {
    return ((board[i][j >>> 5] >>> (j & 31)) & 1) != 0;
}
For valid , j >>> 5 is and ranges from zero to 31. The bit mask j & 31 is the offset . The logical right bit shift brings the desired bit to position zero; the final mask selects only that bit. Even bit 31 of a negative stored word is extracted correctly, because >>> inserts zeros. A different convention, with the leftmost cell in the most significant bit, would instead shift by 31 - (j & 31) and must be used consistently.
Extract one four-bit digit at a time, beginning at the most significant end of the Java int. A lookup string supplies characters, but no library performs the conversion:
java
static String toHex(int value) {
    String digits = "0123456789abcdef";
    String answer = "";
    boolean started = false;
    for (int shift = 28; shift >= 0; shift -= 4) {
        int digit = (value >>> shift) & 15;
        if (started || digit != 0 || shift == 0) {
            answer = answer + digits.charAt(digit);
            started = true;
        }
    }
    return answer;
}
The logical right bit shift >>> inserts zeros, and the bit mask 15 retains exactly the low four bits of the shifted word. Each emitted character is therefore the corresponding hexadecimal digit. The started flag suppresses leading zero digits; the shift == 0 exception makes zero produce "0", rather than an empty string.
A negative Java integer uses two's complement. Its top bit is set, so the first extracted digit is between eight and fifteen and all eight digits are emitted. We interpret its original 32-bit pattern, without taking an absolute value or negating a potentially unnegatable minimum integer. In particular, toHex(19) returns "13", toHex(-1) returns "ffffffff", and toHex(Integer.MIN_VALUE) returns "80000000". There are exactly eight iterations, so for this fixed word size the time complexity is constant.
Use strength reduction on the disassembled hot instructions. In a fixed-width wrapping integer model,
The first replacement is a single left bit shift. For the second, preserve the original operand in a register, shift a copy left by four and subtract the original:
text
rOriginal = x
rResult = rOriginal << 4
rResult = rResult - rOriginal
This avoids a general multiplication if shifts and subtraction are cheaper on the target processor. The two identities hold for positive and negative two's complement operands when only the low result bits are required.
Because only a binary is available, patch the machine instructions and adjust displaced branches or use a jump to a replacement code block if the new sequence does not fit. Preserve live registers and the calling convention. If later instructions consume overflow or other condition flags, or the original multiplication produces a double-width result or traps on overflow, matching only the low-word arithmetic is insufficient: those effects must be reproduced or the transformation rejected. Finally, measure the modified program; a fast hardware multiply need not be slower than several replacement instructions.
Use unsigned inputs as in the preceding parts. Store a 16-bit accumulator , a 16-bit shifted multiplicand , an eight-bit multiplier , and a three-bit iteration binary counter . The sequential circuit has one 16-bit adder, a 16-bit multiplexer selecting or zero from , fixed one-place bit shifts, and load/hold selection for the digital registers. The input values are captured when start is accepted, so later input changes cannot alter the operation.
Figure 1.
The shift-and-add binary multiplier reuses one 16-bit adder for eight iterations
. Details.
Use three control states with the following synchronous transition table. All assignments in a row use the old digital register values and occur together at the active clock edge.
StateConditionRegister updatesNext stateIDLEstart = 0Hold all digital registersIDLEIDLEstart = 1, , , RUNRUN, , , RUNRUN, , ; hold DONEDONEstart = 1Hold all digital registersDONEDONEstart = 0Hold all digital registersIDLE
Reset selects IDLE and clears the digital registers. Set and done = 1 exactly in DONE. A start pulse in IDLE launches one multiplication; further pulses during RUN are ignored. Holding start high cannot repeatedly launch operations: DONE waits for it to go low before rearming. The product remains stored while waiting and through the following IDLE state. There are eight RUN clock edges after the loading edge; the last addition is captured before done becomes high.
For correctness, let denote the captured values. After iterations, for , the loop invariant is
so . Writing , the next accumulation adds , the left bit shift doubles , and the logical right shift changes to . Hence the invariant is preserved. At , , giving . The largest product is , so the accumulator fits. Even the final shifted multiplicand is , so it also fits.
A processor design using a relatively regular instruction repertoire and explicit restrictions on operand forms. Immediate constants may have limited encodings, so extracting low bits with two bit shifts can avoid constructing a large bit mask in a temporary processor register. The benefit depends on the actual instruction set. A compact example appears in the Thumb 16-bit instruction set quick reference by Arm, whose logical bitwise AND instruction uses a processor register operand while shifts accept small immediate counts.