目录
3.34
A:存放的值为x
B:
int rfun(unsigned x){
if( x==0 ) return ( x );
unsigned nx=( x>>1);
int rv=rfun(nx);
return ( (x & 0x1) +rv );
}
在汇编代码第3行中,testl判断了x是否为0,如果为0则会影响标志位ZF,ZF=1时,je就会跳转至.L3即return 0;
C:
该函数通过递归调用的方式,实现了计算一个无符号数x中1的个数的功能。通过不断地将x右移,判断x是否为零,若为零则递归“向下”过程结束,开始不断返回,在返回过程中判断当前x最低位是否为1,为1则当前rv+1返回上一级,否则直接返回rv。
3.56
A:
变量 寄存器
x %esi
n %ebx
result %edi
mask %edx
B:
result:1431655765
mask:-2147483648
C:
mask !=0;(汇编代码第十一行)
D:
((unsigned)mask)>>n;
因为shrl实现的是无符号整数右移,所以要先转成unsigned
E:
result^=(x&mask);(汇编代码第7-8行)
F:
int loop(int x, int n)
{
int result=( 0x55555555 );
int mask;
for(mask=( 0x80000000 ); mask( !=0 ); mask=( ((unsigned)mask)>> (n&0x11) ) ){
result ^=( x&mask);
}
return result;
}
3.59
int switch_prob(int x, int n)
{
int result = x;
switch(n)
{
case 40:
case 42: ((unsigned)result)<<=3; break;
case 43: result>>=3; break;
case 44: ((unsigned)result)<<=3; result-=x;
case 45: result*=result;
case 41:
default: result+=0x11;
}
return result;
}
对照上课课件的建立过程,可以对这一题的解答有所帮助;
对比得知,default的位置:8048435
推出这一步之后其他的便迎刃而解!
中间有一句话没明白是干什么的:汇编第12行 lea 0x0(%esi), %esi
3.66
通过观察test函数,我们能先大体推断出结构体a应该有两个参数,一个是idx一个是一个数组x[ ]
5:读取i (eax)
6:读取*bp (ecx)
7:28*i (ebx)
8:8*i (edx)
9:8*i-i (edx)
10:7*i+(28*i+bp+4) (edx)
11:bp->right=bp+200 (eax) 200=CNT*&a[0]- &(bp->left)
200=CNT*28+4 CNT=7
12:bp->left+bp->right (eax)
13:可以得出(ap->x[ap->idx])的地址为4*(7*i+(28*i+bp+4))+bp+8
实现了ap->x[ap->idx]=n
ap->x[0] 的地址是 bp + 4 + i*size(A) + pos(idx),pos(idx)为结构体A中idx的偏移。
那么ap->x[ap->idx] 的地址是 bp + 4 + i*size(A) + pos(idx) + 4*(ap->idx)。
第10行,edx的结果是 7i + (bp+4 + 28*i),那么(bp+4 + 28*i)是什么呢?它很可能是bp中的a[i]的首地址。我们先这样猜测,于是size(A) = 28,并且地址(bp+4 + 28*i)中存放的值为ap->idx。
另一方面:4*edx = 28*i + 4* (bp+4 + 28*i) = i*size(A) + 4*&(ap->idx)。
所以,4*edx+8+bp 就应该等于bp + 4 + i*size(A) + pos(idx) + 4*(ap->idx)
所以这里pos(idx)=4;
所以结构体a中的数组应该是6个大小的整形数组
A:7
B:
typedef struct{
int idx
int x[6];
}a_struct;