3.34
A:
寄存器%ebx保存参数x的值,即未被移位的x。
B:
int rfun(unsigned x)
{
if (x == 0)
return 0;
unsigned nx = x >> 1;
int rv = rfun(nx);
return ((x & 0x1) + rv);
}
c:
计算参数x中位的和,递归计算除了最低位外所有位的和,然后再加上最低位得到结果。
3.56
A:
%esi保存x
%ebx保存n
%edi保存result
%edx保存mask
B:
result初值为1431655765(10) ,即0x55555555(16)。
mask初值为-2147483648(10),即0x80000000(16)。
C:
测试条件为mask是否为0
D:
mask右移(n&0x000000ff)位
E:
result^= (mask & x)
F:
int loop(int x, int n)
{
int result = 0x55555555;
int mask;
for (mask = 0x80000000; mask != 0; mask = ((unsigned)mask) >> (n & 0x000000ff))
{
result ^= (mask & x);
}
return result;
}
注意逻辑移位要强制转化为unsigned!
3.59
开头将n与40相减后的结果与5比较,说明参数为40~ 45。6个地址分别代表case40~45的开头。
补全代码:
int switch_prob(int x, int n)
{
int result = x;
switch (n)
{
case 40:
result = ((unsigned)result) >> 3;
break;
case 41:
result += 0x11;
break;
case 42:
result = ((unsigned)result) >> 3;
break;
case 43:
result = result >> 3;
break;
case 44:
result = ((unsigned)result << 3) - x;
result *= result;
result += 0x11;
break;
case 45:
result *= result;
result += 0x11;
break;
default:
result += 0x11;
break;
}
return result;
}
注意逻辑移位要强制转化为unsigned!
3.66
第四行%ebp+8中就是i,即%eax=i,第13行mov指令中的%eax存放的是函数第一行中计算的n,所以前面的第11和第12行中,%ebp+0xc存放的是 bp->left, %ebp+0xc+0xc8存放的是 bp->right,所以a_struct[CNT]共占196字节(200-4)。
第9行存在%edx内的是7i,第10行,左边的是M[bp+4+28i],应该就是a[i]所在的地址,由此我们知道a_struct一个应该占28字节,196÷28=7,所以CNT=7。
第13行,右边0x8(%ecx,%edx,4),也就是(4%edx+bp+8),实际上也就是是(bp+4+28i+4+4M[bp+4+28i])。
所以“bp+4+28i”定位到a[i];“+4”是因为有idx是4字节,也证明idx应该在结构中定义在前面;“+4M[bp+4+28i]”定位到bp->a[i]->x[bp->a[i]->idx],也就是ap->x[ap->idx]。
所以可以得到,一个a_struct共28字节,int型的x占4字节,剩下24字节应该就是一个6位int数组,故int x[6]。
A:
CNT=7
B:
typedef struct
{
int idx;
int x[6];
} a_struct;