
【最新】关于arm的立即数处理.docx
3页立即数方式(ARM)——彻底解析 2010-08-01 16:53:30| 分类: 转载博文 | 标签: |字号大中小 订阅 终于彻底的搞定了啥是立即数方式,其实理解最好的办法就是举例子,印象最深的办法就是自己动手! 立即数方式:每个立即数由一个 8 位的常数循环右移偶数位得到其中循环右移的位数由一个 4 位二进制的两倍表示 如果立即数记作,8 位常数记作 immed_8,4 位的循环右移值记作 rotate_imm,则有:=immed_8 循环右移( 2*rotate_imm)这样并不是每一个 32 位的常数都是合法的立即数,只有能够通过上面构造方法得到的才是合法的立即数下面的常数是合法的立即数:0xff,0x104,0xff0,oxff00下面的数不能通过上述构造方法得到,则不是合法的立即数:0x101,0x102,0xFF1同时按照上面的构造方法,一个合法的立即数可能有多种编码方式如 0x3f0是一个合法的立即数,它可以采用下面两种的编码方式:immed_8=0x3f,rotate_imm=oxe 或者immed_8=oxfc,rotate_imm=0xf转换为二进制形式如下:ox3f=0000 0000 0000 0000 0000 0000 0011 1111oxe=14(十进制 ) 2*14=28∴,ox3f 循环右移 28 位得到如下:0000 0000 0000 0000 0000 0011 1111 0000=ox3f0immed_8=oxfc,rotate_imm=0xf 的转换如下:oxfc=0000 0000 0000 0000 0000 0000 1111 1100rotate_imm=oxf=15(十进制) 15*2=30所以 oxfc 循环右移 30 位得到如下结果:0000 0000 0000 0000 0000 0011 1111 0000=ox3f0可以看出,结果是一样的!!!但是,由于这种立即数的构造方法中包含循环移位操作,而循环移位操作会影响 CPSR 的条件标志位 C。
因此,痛一个合法的立即数由于采用了不同的编码方式,将使得某些质量的执行产生不同的结果,这是不能允许的ARM 汇编编译器按照下面的规则生成立即数的编码1.当立即数数值在 0 和 0xFF 范围时,零immmed_8=,rotate_imm=0.、2.其他情况下,汇编编译器选择使 rotate_imm 数值最小的编码方式所以ox3f0 的正确表示法是第一种/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////解释二:一条典型的 ARM 指令语法格式分为如下几个部分: {} {S} ,{,} 其中,是指令助记符,是必须的,而{}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行 ) opcode 指令助记符,如 LDR,STR 等 cond 执行条件,如 EQ, NE 等 S 是否影响 CPSR 寄存器的值,书写时影响 CPSR,否则不影响 Rd 目标寄存器 Rn 第一个操作数的寄存器 operand2 第二个操作数 其指令编码格式如下: 31-28 cond 27-25 001 24-21 opcode 20 S 19-16 Rn 15-12 Rd 11-0 ( 12 位) operand2 对其中的 operand2 的常数表达式有这样的规定:“该常数必须对应 8 位位图,即常数是由一个 8 位的常数循环右移偶数位得到的。
这句话的意思是说,当用12 位第二操作数来表示一个 32 位立即数时,采用的是将 8 位数通过移位的方式来实现的,其中 12 位第二操作数的低八位存放被移位的“基本”数(取值范围为 0 到 255),而高四位存放的是循环右移的位数,因为是四位二进制数,所以取值范围位为 0 到 15,而对应的移位位数则为 0 到 30 位(因为移动的可能只有 31 种),也就是说若 “移位”数为 0,则表示“基本”数不变,若“移位” 数为1,则表示将 “基本”数在 32 位数字空间中循环右移 2 位,若“移位”数为 5,则表示将“基本 ”数在 32 位数字空间中循环右移 10 位,若“移位”数为 10,则表示将“基本”数在 32 位数字空间中循环右移 20 位,依次类推举例表示: AND R1,R2,#0xff 当处理器处理这条指令的第二操作数 0xff 时,因为 0xff 为 8 位二进制数,所以处理器就将其直接放进 8 位“基本”数中,而 4 位“移位”数则为 0. AND R1,R2,#0x104 当处理器处理这条指令的第二操作数 0x104 时,因为此时 0x104 已经超过了 8位二进制数,所以处理器就要将其“改造”一下,我们先把 0x104 转换成二进制0000 0000 0000 0000 0000 0001 0000 0100,我们可以看到,这个数是 0000 0000 0000 0000 0000 0000 0100 0001 通过循环右移 30 位得到的,因此改造后的结果是 8 位“ 基本”数中存放 0100 0001,而“移位”数为 15。
AND R1,R2,#0xff000000 当处理器处理这条指令的第二操作数 0xff000000 时,处理器同样要对其“改造”,我们先把 0xff000000 转换成二进制 1111 1111 0000 0000 0000 0000 0000 0000,我们可以看到,这个数是 0000 0000 0000 0000 0000 0000 1111 1111通过循环右移 8 位得到的,因此改造后的结果是 8 位“基本”数中存放 1111 1111,而“ 移位” 数为 4 我想,通过以上的三个例子,就应该明白了 8 位位图的原理了但是,有些数并不符合 8 位位图的原理,这样的数在进行程序编译时,系统将会提示出错,下面再举几个违反 8 位位图的例子:比如 0x101,转换成二进制后位 0000 0000 0000 0000 0000 0001 0000 0001,像这个数,无论向右循环几位,都无法将两个 1 同时放到低 8 位中,因此不符合 8 位位图;再比如 0x102,转换成二进制后位 0000 0000 0000 0000 0000 0001 0000 0010,如果将两个 1 同时放到低 8 位中,即转换成二进制后为 0000 0000 0000 0000 0000 0000 1000 0001,需要将此二进制数向右移 31 位,这也不符合循环右移偶数位的条件,因此 0x012 也不符合 8 位位图;再举一个 0xff1,转换成二进制后将会有 9 个1,不可能将其同时放入 8 位中,因此当然也不符合啦。
通过正反例的比较,可以总结如下:第一,判断一个数是否符合 8 位位图的原则,首先看这个数转换成二进制后 1 的个数是否不超过 8 个,如果不超过 8 个,再看这 n 个 1(n<=8)是否能同时放到 8 个二进制位中,如果可以放进去,再看这八个二进制位是否可以循环右移偶数位得到起初被判断的那个数值,如果可以,则此数值即为符合 8 位位图原理,否则,不符合第二,用 12 位的编码来表示一个任意的 32 位数是不可能的,只能通过循环右移八位二进制数偶数位来得到一部分 32 位数,其余的无法表示的 32 位数,只有通过其它途径获得了,比如 0xffffff00,可以通过 0x000000ff 按位取反得到,因此在以后的编程中,一定要注意用到的第二操作数是否符合 8 位位图。
