add
,例如sym.imp.__libc_start_main :
.plt:0x000082bc 00c68fe2 add ip, pc, 0, 12; after execution ip=0x82c4
.plt:0x000082c0 08ca8ce2 add ip, ip, 8, 20; after execution ip=0x102c4
.plt:0x000082c4 48fdbce5 ldr pc, [ip, 0xd48]!
我想知道这行
.plt:0x000082c0 08ca8ce2 add ip, ip, 8, 20;
它将把
#0x8000
添加到ip寄存器中。我的问题是为什么#0x8000
?我会假设是:
ip = ip + (8<<20)
所以
0x800000
却更像是ip = ip + (8<<(20-8))
为什么?我总是必须从班次中减去8吗?
#1 楼
这是32位系统上的循环移位。循环移位
在计算机编程中,循环移位(或按位旋转)是
移位运算符,用于移位其操作数的所有位。与
算术移位不同,循环移位不会保留数字的符号
,也不会将数字的指数与其有效位数(有时称为尾数)区分开。与逻辑移位不同,空位
位置不填充零,而是填充不按顺序移位的位
。
了解代码
第一行:
由于在
add ip, pc
上的旋转操作仍为0,因此将其简单地翻译为#0
。行:让我们分解操作码并理解有问题的行:
由于字节顺序,应该这样阅读操作码:
IP = PC + (0 << 12) = PC + 0
-始终执行此指令e28cca08
-立即添加e
-Rd是ip 28
-Rn是ip c
-8向右旋转20 事实是,它不是
c
,而是a 08
,因为我们使用的是32位系统,并且是循环移位。 > 这是一个C代码,基于Wikipedi的示例显示循环移位a:
#include <stdint.h> // for uint32_t, to get 32bit-wide rotates, regardless of the size of int.
#include <limits.h> // for CHAR_BIT
uint32_t rotl32 (uint32_t value, unsigned int count) {
const unsigned int mask = (CHAR_BIT*sizeof(value)-1);
count &= mask;
return (value<<count) | (value>>( (-count) & mask ));
}
uint32_t rotr32 (uint32_t value, unsigned int count) {
const unsigned int mask = (CHAR_BIT*sizeof(value)-1);
count &= mask;
return (value>>count) | (value<<( (-count) & mask ));
}
int main()
{
printf("Result: 0x%x\n",rotr32(8,20));
return 0;
}
代码将输出:
Result: 0x8000
#2 楼
在arm的正式文档中提出当s = 1且RD = R15(PC)时,此指令用于保存状态寄存器CPSR,而不进行计算
评论
我看到它向右旋转而不是向左旋转,谢谢!顺便说一句。行中“不是8 << 20,而是8 <<(32-12)”的错字应为8 >>(32-12)
–生锈
17年8月21日在19:14