深入理解计算机系统第三章程序的机器级表示 家庭作业

深入理解计算机系统第三章程序的机器级表示 家庭作业_第1张图片

程序的机器级表达


开工日期:2018年5月10号 完成日期:2018年5月18日 耗时:8日
配置:centOS 7 64位+gcc4.8.5
推荐大家一个网站compiler explore。很方便


3.58

long decode2(long x,long y,long z)
{    
    //x in %rdi,y in %rsi,z in %rdx
    y = y-z;
    x = x*y;
    long a = y;
    a<<=63;
    a>>=63;
    a = a^x;
    return a;
}



dest in rdi,x in rsi,y in rdx
store_prod:
    movq %rdx,%rax           
    cqto                //把y的符号位放在rdx
    movq %rsi,%rcx  
    sarq $63,%rcx       //把x的符号位放在rcx
    imulq %rax,%rcx       
    imulq %rsi,%rdx
    addq %rdx,%rcx
    mulq %rsi
    addq %rcx,%rdx
    movq %rax,(%rdi)
    movq %rdx,8(%rdi)
    ret

深入理解计算机系统第三章程序的机器级表示 家庭作业_第2张图片
第一个乘法: x符号*y

第二个乘法 : y符号*x

第三个乘法 : x和y的无符号相乘。

由上图可知,x和y的无符号相乘,x和y的有符号相乘相差的是 : 2^64*(x符号*y + y符号*x)
所以第10行把这个加到了rdx。



3.60
A:

寄存器
x %rdi
n %esi
result rax
mask rdx

B

result 0
mask 1

C
mask!=0

D
mask = mask<

F:
long loop(long x,int n)
{
    long result = 0;
    long mask;
    for(mask=1;mask!=0;mask=mask<return result;
}




3.61
从cread()的矛盾里,要使用条件传送指令,就必须算出2种可能性,但是*xp可能是空指针,会产生间接使用空指针的错误。这里,我加一层指针. (大家可以看看linux之父的这个演讲。他在这个演讲里讲了二重指针。很有意思)linux

long cread_alt(long *xp){
    int **p=&xp;
    int zero=0;
    return *(*p?*p:&zero);
}

得到的汇编代码是(要好-O1优化)

cread_alt:
  movl $0, -4(%rsp)
  leaq -4(%rsp), %rax
  testq %rdi, %rdi
  cmove %rax, %rdi
  movslq (%rdi), %rax
  ret




3.62

typedef enum{MODE_A,MODE_B,MODE_C,MODE_D,MODE_E}mode_t;

long switch3(long *p1,long *p2,mode_t action)
{
    long result=0;
    switch(action){
    case MODE_A:
        result = *p2;
        *p2 = *p1;
        break;
    case MODE_B:
        result = *p1 + *p2;
        *p1 = result; 
        break;
    case MODE_C:
        *p1=59;
        result = *p2;
        break
    case MODE_D:
        *p1 = *p2;
        result = 27;
        break; 
    case MODE_E:
        result = 27;
        break;
    default:
        result = 12;
    }
    return result;
}




3.63

long switch_prob(long x,long n)
{
    long result = x;
    switch(n){
        case 60:
        case 62:
            result = 8*x;
            break;
        case 63:
            result = x>>3;
            break;
        case 64:
            result = (x<<4)-x ; //result = x*15;
            x = result;
        case 65:
            x*=x;
        default:
            result = x+0x4b;
    }
    return result;
}




3.64
A:
&A[ i ] [ j ] [ k ] = Xd+L(T*S*i+T*J+k)
B:
从汇编代码可得,①65*i+13*j+k ②R*T*S *8 = 3640

R 7
S 5
T 13




3.65
A

&A[i][j] 在%rdx

B

&A[j][i]在%rax

C

M=15




3.66

#define NC(n) 4*n+1
#define NR(n) 3*n




3.67
A

     ------------------------------------------- 
rsp                     x
+8   |                  y                      |
+16  |                 &z                      |
+24  |                  z                      |
     |                                         |
     |                                         |
     |                                         |
     |                                         |
     |                                         |

                    ........
+64  |                                         | <-rdi
     |                                         |
     |                                         |
     |                                         |
     |                                         |

B
%rdi
C

s.p 24(%rsp)
s.a[0] 16(%rsp)
s.a[1] 8(%rsp)

这里大家可能有疑问,访问结构参数s的元素,为什么和栈上的不同。原因是call 调用函数时,会使rsp+8
D
放在了%rsp(旧)+64
E

     ------------------------------------------- 
rsp                     x
+8   |                  y                      |
+16  |                 &z                      |
+24  |                  z                      |
     |                                         |
     |                                         |
     |                                         |
     |                                         |
     |                                         |

                    ........
+64  |                y                        | <-rdi
     |                x                        |
     |                z                        |
     |                                         |
     |                                         |

F
参数:放在栈上。
返回值:放在栈上.



3.68
为什么这题值3个星呢,难就难在了对齐上。

从会汇编上看,可以得到一些偏移地址。
typedef struct{
    int x[A][B];
    long y;  //偏移地址是184
}str1;
typedef struct{
    char array[B];
    int t;   //偏移地址是8
    short s[A];
    long u;   //偏移地址是32
}str2;
分析:
在str2里,int t的偏移地址是8,证明char array[B]占5~8个字节,也就是说,5≤B≤8 
long u的偏移地址是32,证明short s[A]占16~20字节,也就是说,8≤A≤10
在str1里,Long y 的偏移地址是184,证明int x[A][B]占180~184个字节,也就是说,45≤AB≤46.

综上

A 9
B 5




3.69
被这题坑了,这题用的数都是十六进制。

mov 0x120(%rsi),%ecx      ;把bp->last放在ecx,得到last的偏移量是288
add (%rsi),%ecx           ;bp->last+bp->first
lea (%rdi,%rdi,4),%rax    ; 5i放在%rax  
lea (%rsi,%rax,8),%rax    ; (5i*8+bp)
mov     0x8(%rax),%rdx    ; (5i*8+bp)+8
movslq  %ecx,%rcx         
mov %rcx,0x10(%rax,%rdx,8)    ;16+%rax是&ap->x,%rdx*8是ap->idx 
}

A:
第4行,40i+bp+8。我们可以推测sizeof(a_struct)=40,在b_struct的对齐是8.再加上前面last的偏移量是288,CNT = (288-8)/sizeof(a_struct) = 7;
B:
第6行,movslq %ecx,%rcx 证明ap->x[ ]的类型是long
16+%rax是代表&ap->x 。可以得到idx比x前,且是long类型。

typedef struct{
    long idx;
    long x[4];
}a_struct;




3.70
A

e1.p 0
e1.y 8
e2.x 0
e2.next 8

B
16 bytes
C

void proc(union ele *up){
    up->e2.x =*(up->e2.next->e1.p) - (up->e2.next->e1.y);
}
分析:
1   proc:
2       movq    8(%rdi), %rax     ;(这里%rax已经是up->e2.next)
3       movq    (%rax), %rdx      ;访问up->e2.next->e1.p 
4       movq    (%rdx), %rdx      ;访问*(up->e2.next->e1.p)
5       subq    8(%rax), %rdx     ;8(%rax)是up->e2.next->e1.y.   
6       movq    %rdx, (%rdi)      ;(%rdi)是ele.e2.x
7       ret




3.71

void good_echo(){、
    const int BufSize = 32;
    char buf[BufSize];
    if(fgets(buf,BufSize-1,stdin) || ferror(stdin))
        return;
    puts(buf);
}




3.72
A

如果n是奇数
    8n+24
如果n是偶数
    8n+16

B
(%rsp+15) &(-16)的结果:

%rsp后四位 __
0000 %rsp
0001 %rsp+15
0010 %rsp+14
0011 %rsp+13
0100 %rsp+12
0101 %rsp+11
0110 %rsp+10
0111 %rsp+9
1000 %rsp+8
1001 %rsp+7
1010 %rsp+6
1011 %rsp+5
1100 %rsp+4
1101 %rsp+3
1110 %rsp+2
1111 %rsp+1

C

n s1
min 0001结尾
max 0000结尾

D
从B的表格可以看出,P地址的后4位都是0000,也就是保证了16字节对齐



3.73

—— CF ZF PF
x>0 0 0 0
x=0 0 1 0
x<0 1 0 0
NaN 1 1 1

深入理解计算机系统第三章程序的机器级表示 家庭作业_第3张图片
内联汇编指南

find_range:
    vxorps %xmm1, %xmm1, %xmm1
    vucomiss %xmm1,%xmm0
    je .L1    
    jne .L2  
.L1:
    jb .NaN
    jae .L3
.L2:
    jb .L4
    jae .L5
.NaN:
    movl $2,%eax
    ret
.L3:
    movl $0,%eax
    ret
.L4:
    movl $-1,%eax
    ret
.L5:
    movl $1,%eax
    ret




3.74
warning未经测试
在不久后测试
靠书上的条件传送指令根本做不出这道题()

—— CF ZF PF
x>0 0 0 0
x=0 0 1 0
x<0 1 0 0
NaN 1 1 1

答案可以参考这个



3.75
A

实部 虚部
%xmm0 %xmm1
%xmm2 %xmm3

B
实部放在%xmm0,虚部放在%xmm1

你可能感兴趣的:(深入理解计算机系统家庭作业)