3

I recently started playing with ARM assembly and notice I only seem to be about to move 32 bit values into registers but what if i wanted to only move 8 or 16 bits into the registers like in x86 assembly. i.e.

arm
eor r0, r0
mov r0, #128

x86
xor eax, eax
mov al, 0x80

r0 now contains 0x80 but it is a 32 bit register so it will contain 0x00000080

if this was x86 i could use al (8 bit register) to manipulate the last byte instead of eax (32 bit register).

tl;dr Are there small registers in ARM assembly?

tozhan
  • 413
  • 1
  • 7
  • 18
  • 1
    Do you have any documentation on ARM assembly? To change only the lower x bits, you need to clear them with AND, then set with OR. – Jongware May 17 '14 at 22:34
  • RISC architectures almost always work on the whole register. There's no way to operate on a small part of the register – phuclv Apr 10 '16 at 09:24
  • related: [Direct Arithmetic Operations on Small-sized Numbers in RISC Architectures](https://stackoverflow.com/q/47666871/995714) – phuclv Apr 23 '19 at 09:36
  • That x86 code saves 1 byte of code-size vs. 5-byte `mov eax, 0x80`, but it's not worth it. Compilers will use `mov eax, 0x80` because it's more efficient to run one single-uop instruction instead of 2, even if it costs an extra byte of code size. A better example would be something like `shl al, 4` to implement `(uint8_t) (x<<4)`, not shifting bits past that 8-bit boundary into the higher parts of EAX. – Peter Cordes Nov 23 '20 at 09:23

2 Answers2

7

No. ARM registers are 32-bit1.

However, assuming you're on a recent enough architecture version (ARMv6T2 or later) you can use the BFI and UBFX instructions to insert/extract an arbitrary slice of a register from/to the bottom of another without affecting the other bits. Doing the same with an immediate operand is a little trickier since MOV zero-extends immediates2 (i.e. the eor r0,r0 in your example is entirely redundant) - you'd either have to use AND and ORR as mentioned, or use an intermediate register for MOV followed by BFI.


[1] Well, "fixed-size" is more appropriate once you consider AArch64 state - there you have 32-bit and 64-bit views of the same registers, but any writes to a 32-bit view implicitly zero the upper 32 bits, so the same principle still applies (i.e. it doesn't allow you to pretend you have twice as many half-sized registers like an 8086).

[2] The exception to this is MOVT, which loads an immediate into the upper 16 bits of a register without touching the lower half (to allow loading a full 32-bit immediate with a MOVW/MOVT pair)

Notlikethat
  • 20,095
  • 3
  • 40
  • 77
3
arm
eor r0, r0
mov r0, #128

why not just do this instead:

mov r0,#128

No reason for the eor...

No you dont have the same 8 bit history with arm, so the registers started off from the beginning as 32 bit. but you still have a number of instructions that help you do sub-32 bit operations on the registers.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • I figured the xor was pointless since the entire 32 bits are modified but I left it in because symmetry is pretty... – tozhan May 18 '14 at 17:48
  • understood, you could have just used a 32 bit immediate in x86 as well as an alternate example since you were trying to modify the whole 32/64 bit register not just 8 bits in your example. – old_timer May 18 '14 at 19:01