在ARM立即数寻址中,指令中的立即数是有一个8位的常熟和移动的4 位偶数位得到的,所以每一条指令都包含一个常数X和移位值Y,得到的立即数=X循环右移(2*Y)
给定一个立即数,判断其是否合法可以分三步:首先将给定的立即数写成32位二进制的形式;然后看能不能用一个8位的二进制数包括所有含1的部分,如不能则非法;最后看这个8位二进制数能不能循环右移偶数位得到给定的立即数,不能数则非法。
下面给出判断一个16进制的数是否为ARM的立即数的C语言代码;
#include <stdio.h>
#define ture 1
#define false 0
unsigned int rightmove(int num,int bit) ;//把num数右移bit位
void prin2(unsigned int num) ; //十进制转打印二进制数
bool judge(unsigned int num) ; //判断是否是立即数
int main()
{
bool decide ;
unsigned int num ;
printf("本台电脑unsigned int类型是%d位\n",sizeof(unsigned int)*8) ; //打印电脑int类型是否是32位字节,输出4则是
printf("请输入16进制的判断数") ;
while(1)
{
scanf("%p",&num) ;
decide = judge(num) ;
decide == ture ?printf("yes!\n") : printf("no!\n") ;
}
return 0 ;
}
/*a
总长度N(8 16 32)
循环左移n (a >> (N - n)) | (a >> n)
循环右移n (a << (N - n)) | (a >> n)
*/
unsigned int rightmove(unsigned int num,int bit) //把num数右移bit位
{
num = (num << (32 - bit)) | (num >> bit) ;
return num ;
}
bool judge(unsigned int num) //判断是否是立即数
{
int i ;
unsigned int num_bak ;
i = 32 ;
for(i = 0 ;i < 32 ;i++)
{
num_bak = rightmove(num,i) ;
//printf("%10x ",num_bak) ;
prin2(num_bak) ;
if(num_bak <= 0x00ff )
{
if(i % 2 == 0)
{
return true ;
}
}
}
return false ;
}
void prin2(unsigned int num)
{
int i = 0 ,j = 31;
char bit[32] ;
for(i = 0 ;i < 32 ;i++)
{
bit[j--] = (num >> i) & 0x01 ;
}
j = 0 ;
while(j < 32)
{
printf("%d",bit[j++]) ;
if(j % 4 ==0 )
{
printf(" ") ;
}
}
puts("") ;
}
//注意:输入的16进制的数必须是unsigned int 类型,如果不是,则会导致判断错误,因为有一个符号位会干扰移位值与0xFF的比较。代码中输出了每一次移位后的二进制数,请读者根据现实理解立即数的有效判断。