首先,您需要 infocenter.arm.com 上的 ARM 架构参考手册 (ARM ARM),参考手册,获取最旧的(armv5 或其他)。指令集在那里定义良好。
其次,你为什么不组装一些指令,看看会发生什么?
;@test.s
cmp r1, r0
add r0, #0x1a
无论您拥有什么交叉汇编器(请参阅构建 gcc 目录中的http://github.com/dwelch67/raspberrypi以获取脚本,只需在该脚本中通过 binutils 运行)
arm-none-linux-gnueabi-as test.s -o test.o
arm-none-linux-gnueabi-objdump -D test.o
arm-none-linux-gnueabi vs arm-none-elf vs arm-elf,等等,这无关紧要,都一样
Disassembly of section .text:
00000000 <.text>:
0: e1510000 cmp r1, r0
4: e280001a add r0, r0, #26
完整的 32 位 arm 指令(不是 thumb)的前四位是条件代码,请参阅 ARM ARM 中的条件字段部分。0xE 表示总是,总是执行这条指令。0b0000 是 eq 仅在设置 z 标志时执行,0b0001 ne 仅在 z 清零时执行,等等。
在 ARM 中将 ARM 推入 arm 指令集,然后按字母顺序排列 arm 指令,然后找到 cmp 它以 cond 00I10101 rn sbz shifter 开头
从上面的 cmp 指令中,我们看到 1110 000101010001 ... 所以 I 是零位 15:12 是零位 27:26 是零位和 24:21 是 1010 所以这是一个 cmp 指令
上面的第 19 位到第 16 位是 0b001,它是 rn 所以 rn = 1 (r1) 用于 ARM ARM 中的移位器操作数,它告诉您查看寻址模式 1 数据处理操作数,并在 pdf 中具有指向页面的链接
我们知道我们希望第二个操作数只是一个寄存器,即所谓的数据处理操作数 - 寄存器和页码,转到该页上的那个页面 15:12 是 rd 11:4 是零,3:0 是 rm . 我们从 cmp 指令中知道它说 15:12 应该为零,我想知道它是否在乎, cmp 不会将结果存储到寄存器中,因此不使用 rd 。rm 被使用,在这种情况下我们想要 r0,所以 0b0000 进入 3:0 还要注意它显示位 27:25 为零,在 cmp 指令中 25 是 I,我们现在知道我们想要一个零,所以
在 cmp 页面和这个数据处理之间 - register 页面我们有整个画面
1110 condition
000
1010 opcode
1 S (store flags, that is a 1 for a cmp to be useful)
0001 rn
0000 rd/dont care/sbz
00000
000
0000 rm
cmp rn,rm
cmp r1,r0
add 类似但使用立即数,因此请转到 alpha 指令列表中的 add 指令。我们现在从 cmp 知道这类指令的 24:21 是操作码,我们几乎可以直接进入移位器操作数的内容以从那里继续
这次我们正在添加 rd,rn,#immediate
所以寻找#immediate的页面
并且编码是
1110 condition, always
001 (note the immediate bit is set)
0100 (opcode for add for this type of instruction)
0 (S not saving the flags, it would be adds r0,r0,#26 for that)
0000 (rn = r0)
0000 (rd = r0)
现在到了有趣的部分,我们可以对 26 种不同的方式进行编码。位 7:0 是立即数,位 11:8 允许旋转立即数,26 是 0x1A,我们可以简单地将 0x1A 放在低 8 位并将旋转设置为 0,这就是 gnu 汇编程序所做的。可能会在低 8 位中放入 0x68,在 rotate_imm 字段 1101000 中放入 1,向右旋转 1*2 位是 11010 = 0x1A = 26。