assemblyarm32-bitmachine-codeinstruction-encoding

Do the bytes "00 10 A1 B3" make sense in Arm 32-bit architecture?


The bytes 00 10 A0 B3 decodes to movlt r1, #0 in the arm 32-bit architecture.

When I type the bytes 00 10 A1 B3 into the shell-storm online disassembler, it shows "N/A".

However, in the Desmume Emulator Debugger for DS games, when I change the bytes to 00 10 A1 B3, the debugger still shows movlt r1, #0 and the program can actually run without problem (no crashing or behavior difference etc.)

Is this the specific behavior of the Debugger that I'm using, or is it a general 32-bit arm architecture specification thing (in such case the shell-storm online disassembler is bugged).


Solution

  • In ARM mode, b3a01000 is indeed the right encoding for movlt r1, #0. The ARM7TDMI manual gives the instruction format of this class of instruction as:

    CCCC00IXXXXSNNNNDDDDMMMMMMMMMMMM
       |  |   ||   |   |           `-- 2nd operand
       |  |   ||   |   `-------------- destination operand
       |  |   ||   `------------------ 1st operand
       |  |   |`---------------------- 0 do not set flags
       |  |   |                        1 set flags
       |  |   `----------------------- opcode
       |  `--------------------------- 0 2nd operand is register
       |                               1 2nd operand is immediate
       `------------------------------ conditional
    

    For both b3a01000 and b3a11000, the conditional is 1011 indicating LT, the I field is 1 indicating an immediate operand, the opcode field is 1101 indicating a MOV instruction, the S field is 0, indicating that flags are not set, the destination operand is 0001, indicating R1, and the 2nd operand is 000000000000, indicating an immediate operand of #0.

    The sole difference is that b3a01000 has a 1st operand field of 0000, indicating R0, whereas b3a11000 has 0001, indicating R1.

    The manual documents the operation of MOV as:

    Rd := Operand 2 (Operand 1 is ignored)

    Therefore, on ARM7TDMI (and ARM9, which has the same architecture), the contents of this field just don't matter and both encode the same instruction.

    In later variants of the ARM architecture such as ARMv7-A, the operand 1 field must be 0000 for the MOV instruction. This is probably why the disassembler doesn't like b3a11000. However, testing on a recent ARMv8-A based system, I find that this restriction is not enforced and a nonzero operand 1 field executes just fine.