20135220谈愈敏--家庭作业汇总

第二章家庭作业

2.59

分值:2分

题目要求:编写一个C表达式,生成一个字,由x的最低有效字节和y中剩下的字节组成。

思想:首先取出x的最低有效字节,采用 x & 0xFF 的方法,取出y的剩下字节采用 y & ~0xFF 的方法,这里都是运用到了与1相与是本身,与0相与是0的思想。

然后考虑到与0相或是本身,把这两部分相或就能得到结果。

具体代码与实践:

744632-20151120225540030-1323380324.png

744632-20151120225548421-2138569342.png

2.60

分值:2分

题目要求:将字节从低(0)到高编号,写出函数实现将参数x的字节i被替换成字节b。

思想:首先思考如果要替换,先将x的字节i变成0,把字节b通过相或的办法“装”到相应位置即可。

将0xFF向左移到对应x的字节i的位置取反后&x就能把字节i变成0,那要左移多少位呢?i字节对应8*i位,即i<<3位,所以第一步是 x & ~(0xFF << (i<<3))。为了能够把b“装”到正确位置,要左移相同的位数,即 b << (i<<3)。最后把这两部分相或即可。

具体代码与实践:

744632-20151120225757733-599396812.png

744632-20151120225806952-2095362666.png

2.61

分值:2分

题目要求:编写一个C表达式,下述条件中产生1,其他情况为0。

A:x的任何位都等于1

思想:为了保证任何位都是1的情况下才输出1,可以先按位取反 ,这样任何位都应该是0,然后运用逻辑运算就可以产生1。

具体代码与实践:

744632-20151120225842983-470903399.png

744632-20151120225854702-67497086.png

B:x的任何位都等于0

思想:为了保证任何位都是0(数值为0)的情况下才输出1,直接运用逻辑运算就可以产生1,只要有一位不是0,这个数值就不是0,逻辑运算后自然会是0.

具体代码与实践:

744632-20151120225925218-1765261862.png

744632-20151120225934374-649243224.png

C:x的最高有效字节中的位都等于1

思想:联系A中的情况,只要把这里的x的最高字节替换A中的x即可,是相似的原理。

那如何取出最高有效字节呢?这里又可以联系2.60中的方法,主体是将x右移得到,那右移多少位呢?计算除最高有效字节以外有多少位:(sizeof(int)-1) << 3

最后套用A中的公式就是:! ~ (x >> ( (sizeof(int)-1) << 3 )

具体代码与实践:

744632-20151120230000046-156979124.png

744632-20151120230020640-1031370549.png

D:x的最低有效字节中的位都等于0

思想:联系B中的情况,只要把这里的x的最低字节替换B中的x即可,是相似的原理。

获取x的最低字节比较简单:x & 0xFF

最后套用B中的公式就是:! (x & 0xFF)

具体代码与实践:

744632-20151120230054249-1412638719.png

744632-20151120230106452-1067627320.png

[问题]多数代码中,scanf函数里用了%p,实现从屏幕直接输入一个16进制的数,这样编译会有一个警告,因为和我定义的数据类型不同,可是依然能够运行,我认为程序运行时,内部数据可以自己转换过来的。如果我用%d,输入10进制的数就不会有这样的问题。

第三章家庭作业

3.66

分值:3分
题目

C程序:

typedef struct {
    int left;
    a_struct a[CNT];
    int right;
}b_struct;

void test(int i,b_struct *bp)
{
    int n = bp->left + bp->right;
    a_struct *ap = &bp->a[i];
    ap->x[ap->idx] = n;
}

反汇编代码:

1   push  %ebp
2   mov   %esp,%ebp
3       push  %ebx
4   mov   0x8(%ebp),%eax
5   mov   0xc(%ebp),%ecx
6   imul  $0x1c,%eax,%ebx
7   lea   0x0(,%eax,8)
8   sub   %eax,%edx
9   add   0x4(%ecx,%ebx,1),%edx
10      mov   0xc8(%ecx),%eax
11      add   (%ecx),%eax
12      mov   %eax,0x8(%ecx,%edx,4)
13      pop   %ebx
14      pop   %ebp
15      ret
中心思想:逆向推断

具体思考过程:

为了方便,先用结构体A表示a_struct。

首先,根据第10和11行,可以得到 CNT*size(A) = 196。

根据12行,知道 ecx + 4*edx + 8为 ap->x[ap->idx]的地址。

ecx存储的是bp(地址)。

ap的地址是 bp + 4 + i*size(A)

我们知道,ap->x[0] 的地址是 bp + 4 + i*size(A) + pos(x),pos(x)为结构体A中x的偏移。

那么ap->x[ap->idx] 的地址是 bp + 4 + isize(A) + pos(x) + 4(ap->idx)。

所以 4edx + 8 = 4 + isize(A) + pos(x) + 4*(ap->idx)。

所以,不难猜测,pos(x)=4,也就是说,在A中,首先是idx,再是x数组。

那么,我们看ap->idx在哪里计算过。

到第9行,edx的结果是 7i + bp[4 + 28*i],

bp[4 + 28*i]是什么呢?它很可能是bp中的a[i]的首地址。

我们先这样猜测,于是size(A) = 28,并且bp[4+28*i]的值为ap->idx。

另一方面:4edx = 28i + 4bp[4+28*i] = isize(A) + 4*(ap->idx)。

所以,我们的猜想是正确的。

因此,size(A) = 28,里面包含了一个int idx和一个数组int x[6]。

总共有多少个A呢?CNT = 196/size(A) = 7。

第六章家庭作业

链接:http://www.cnblogs.com/20135202yjx/p/4954860.html

转载于:https://www.cnblogs.com/tymjava/p/4982570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值