immediate in assembly

aarch64

AArch64 is an ISA with a fixed instruction width of 32-bit. This obviously means there is not enough space to store a 64-bit immediate in a single instruction.

Assign immediate to register

Assigning the same value to the register x0 takes four instructions:

  1. movz x0, 0x7788
  2. movk x0, 0x5566, lsl 16
  3. movk x0, 0x3344, lsl 32
  4. movk x0, 0x1122, lsl 48
  • movz: assigns the given 16-bit value to the position given by the shift operand and zeroes all other bits. 移位 + 其他位置 0
  • movn: assigns the given 16-bit value to the position given by the shift operand and negativing this value. movz 后对各 bit 取反
  • movk: assigns the given 16-bit value to the position given by the shift operand and keeps the value of the other bits. 移位 + 其他位保持原来的值

Using immediate in Add/Sub

All instructions of the add/sub immediate instruction class allow a 12-bit unsigned immediate that can optionally be shifted by 12 bits (1 bit for the shift). If you want to use these instructions with an immediate that can’t be encoded in this format, you have no choice but to use a temporary register and possibly multiple instructions for initializing this register.

加减类的指令提供了 13bits 的空间用于支持立即数: 12bits 用于存放数据, 1bit 用于指示移位(左移 12bits)

Using immediate in Logic

The logical immediate instructions accept a bitmask immediate bimm32 or bimm64. Such an immediate consists EITHER of a single consecutive sequence with at least one non-zero bit, and at least one zero bit, within an element of 2, 4, 8, 16, 32 or 64 bits; the element then being replicated across the register width, or the bitwise inverse of such a value. The immediate values of all-zero and all-ones may not be encoded as a bitmask immediate, so an assembler must either generate an error for a logical instruction with such an immediate, or a programmer-friendly assembler may transform it into some other instruction which achieves the intended result.

N imms immr element size
0 1 1 1 1 0 x aaaaaa 2 bits
0 1 1 1 0 x x aaaaaa 4 bits
0 1 1 0 x x x aaaaaa 8 bits
0 1 0 x x x x aaaaaa 16 bits
0 0 x x x x x aaaaaa 32 bits
1 x x x x x x aaaaaa 64 bits
  • size and length depends N and imms
  • x is position of length
  • rotation depends immr

C++ code to expand how logic immediate generate.

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. // Dumps all legal bitmask immediates for ARM64
  4. // Total number of unique 64-bit patterns:
  5. // 1*2 + 3*4 + 7*8 + 15*16 + 31*32 + 63*64 = 5334
  6. const char *uint64_to_binary(uint64_t x) {
  7. static char b[65];
  8. unsigned i;
  9. for (i = 0; i < 64; i++, x <<= 1)
  10. b[i] = (0x8000000000000000ULL & x) ? '1' : '0';
  11. b[64] = '\0';
  12. return b;
  13. }
  14. int main() {
  15. uint64_t result;
  16. unsigned size, length, rotation, e;
  17. for (size = 2; size <= 64; size *= 2)
  18. for (length = 1; length < size; ++length) {
  19. result = 0xffffffffffffffffULL >> (64 - length);
  20. for (e = size; e < 64; e *= 2)
  21. result |= result << e;
  22. for (rotation = 0; rotation < size; ++rotation) {
  23. printf("0x%016llx %s (size=%u, length=%u, rotation=%u)\n",
  24. (unsigned long long)result, uint64_to_binary(result), size,
  25. length, rotation);
  26. result = (result >> 63) | (result << 1);
  27. }
  28. }
  29. return 0;
  30. }

x86

Accept all immediate, place it at the end of instruction.