• 家庭作业


    第二章作业

    家庭作业2.78:写出函数mul5div8的代码,对于整数参数x,计算5 * x/8,但是要遵循位级整数编码规则。你的代码计算5 * x也会产生溢出。

    分析:

    这相当于计算((x<<2) + x) >> 3,根据题目要求,无需考虑5 * x时产生溢出,但要考虑 x 为负数时的舍入。

    假设 x 的位模式为[b(w-1), b(w-2), ... , b(0)],那么我们需要计算:
    [b(w-1),b(w-2),b(w-3), ... ,b(0), 0, 0]+ [b(w-1),b(w-2),...,b(2), b(1), b(0)],相加后的结果整体右移3位。

    右移三位时,b(1)+0和b(0)+0对结果无影响,b(0)+b(2)如果产生进位,则结果再加一。

    int mul5div8(int x)
    {
    	int b0 = x&1, b2 = (x>>2)&1;
    	int ans = ((x<<2) + x) >> 3;
    	ans += (b0&b2);
    	return ans;
    }
    

    运行结果:

    溢出:

    第三章作业

    家庭作业3.56

    考虑下面的汇编代码:

    	movl	8(%ebp),%esi
    	movl	12(%ebp),%ebx
    	movl	$1431655765,%edi
    	movl	$-2147483648,%edx
    .L2:
    	movl	%edx,%eax
    	andl	%esi,%eax
    	xorl	%eax,%edi
    	movl	%ebx,%ecx
    	shrl	%cl,%edx
    	testl	%edx,%edx
    	jne		.L2
    	movl	%edi,%eax
    

    以上代码是以下整体形式的C代码编译产生的:

    int loop(int x,int n)
    {
    	int result = ;
    	int mask;
    	for(mask= ;mask  ;mask=)
    	{
    		result^ = ;
    	}
    	return result;
    }
    

    这个函数的结果是在寄存器%eax中返回的。检查循环之前、之中、之后的汇编代码,形成一个寄存器和程序变量之间一致的映射。

    A.哪个寄存器保存着程序值x、n、result和mask?

    B.result和mask的初始值是什么?

    C.mask的测试条件是什么?

    D.mask是如何被修改的?

    E.result是如何被修改的?

    F.填写这段代码中所有缺失部分

    分析:

    • x at %ebp+8,n at %ebp+12,返回值为result,且存在%eax中,由此得出

        寄存器  变量
        %esi 	x
        %ebx 	n
        %edi 	result
        %edx 	mask
      

    以及result和mask的初始值result = 1431655765,mask = -2147483648;

    • 检查循环之中的代码可得出,每次循环的运算结果为result^ = mask & x;

    • 由跳转语句jne .L2得知循环的判断条件为是否等于0,结合测试 条件testl %edx,%edx,edx中存放的变量为mask,所以循环条件为mask!= 0

    • movl %ebx,%ecx将n放入%ecx寄存器中,而shrl %cl,%edx语句取%ecx的低八位。说明n是一个不大的数字,每次循环之后将mask左移n位。

    解答:

    int loop(int x,int n)
    {
    	int result = 1431655765;
    	int mask;
    	for(mask = -2147483648;mask!= 0 ;mask = mask>>n)
    	{
    		result^ = mask & x;
    	}
    	return result;
    }
    

    第四章作业

    家庭作业4.43

    IA32pushl指令被描述成要减少栈指针,然后将寄存器存储在栈指针的位置。因此,如果我们有一条指令形如对于某个寄存器REG,pushl REG,它等价于下面的代码序列:

    subl $4,%esp
    movl REG,(%esp)
    

    A.这段代码序列正确的描述了指令pushl %esp的行为吗?请解释。

    B.你该如何改写这段代码序列,使得它能够像对REG是其他寄存器时一样,正确地描述REG是%esp的情况?

    分析:

    A.%esp和其余寄存器的不同之处就在于,%esp是栈指针,始终指向栈顶,pushl %esp 是将 esp 当前的内容入栈。

    B.如果想要描述%esp的情况, REG 是 esp,那么代码是先减去了 esp,然后将减了 4 以后的 REG 移入了 esp。

    解答:

    A.没有正确执行 pushl %esp,pushl %esp 是将 esp 当前的内容入栈。

    B.修改:

    movl REG, %eax
    subl $4, %esp
    movl %eax, (%esp)
    

    第六章作业

    家庭作业6.35

    考虑下面的矩阵转置函数:

    typedef	int array[4][4];
    void transpose2(array dst,array src)
    {
    	int i,j;
    	
    	for(i=0;i<4;i++)
    	{
    		for(j=0;j<4;j++)
    		{
    			dst[i][j]=src[j][i];
    		}
    	}
    }
    

    假设这段代码运行在一台具有如下属性的机器上:

    • sizeof(int)==4。
    • 数组src从地址0开始,而数组dst从地址64开始(十进制)。
    • 只有一个L1数据高速缓存,它是直接映射、直写、写分配的,块大小为16字节。
    • 这个高速缓存总共有32个数据字节,初始为空。
    • 对src和dst数组的访问分别是读和写不命中的唯一来源。

    对于每个row和col,指明对src[row][col]和dst[row][col]的访问是命中(h)还是不命中(m)。

    分析:

    对于写分配的高速缓存,每次写不命中时,需要读取数据到高速缓存中。

    该高速缓存只有 2 个组,src[0] src[2] 对应组 0,src[1] src[3] 对应组 1。

    同理,dst[0] dst[2] 对应组 0,dst[1] dst[3] 对应组 1。

    解答:

    家庭作业6.36

    对于一个总大小为128数据字节的高速缓存,重复习题6.35。

    分析:

    缓存能完全容得下两个数组,所以只会出现冷不命中。

    解答:

  • 相关阅读:
    实现单台测试机6万websocket长连接
    关于ArcGIS10.0中的栅格计算中的函数
    .NET破解之迅捷PDF转换器(续)
    ArcEngine 0x8004023C
    VS2010中重命名项目
    地理数据库本身不能加密
    ArcEngine尝试读取或写入受保护的内存
    利用路由器连接别人家的网络
    ArcGIS的许可文件问题
    MapGIS转Shp文件的单位问题
  • 原文地址:https://www.cnblogs.com/July0207/p/4902752.html
Copyright © 2020-2023  润新知