计算机系统基础作业
假设某个C语言函数func的原型声明如下:
void func(int *xptr, int *yptr, int *zptr);
函数func的过程体对应的机器级代码用AT&T汇编形式表示如下:
movl 8(%ebp), %eax
movl 12(%ebp), %ebx
movl 16(%ebp), %ecx
movl (%ebx), %edx
movl (%ecx), %esi
movl (%eax), %edi
movl %edi, (%ebx)
movl %edx, (%ecx)
movl %esi, (%eax)
请回答下列问题或完成下列任务:
(1)在过程体开始时三个入口参数对应实参所存放的存储单元地址是什么?(提示:当前栈帧底部由帧指针寄存器EBP指示,栈从高地址向低地址生长,参数入栈顺序为从右到左,因此总是最右边参数的地址最大)
(2)根据上述机器级代码写出函数func的C语言代码
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
(1)xptr、yptr、zptr对应实参所存放的存储单元地址分别为:R[ebp]+8、R[ebp]+12、R[ebp]+16。
(2)函数func的C语言代码如下:
void func(int *xptr, int *yptr, int *zptr)
{
int tempx = *xptr;
int tempy = *yptr;
int tempz = *zptr;
*yptr = tempx;
*zptr = tempy;
*xptr = tempz;
}
题目解析:
(1)xptr、yptr、zptr对应实参所存放的存储单元地址分别为:R[ebp]+8、R[ebp]+12、R[ebp]+16。
(2)函数func的C语言代码如下:
void func(int *xptr, int *yptr, int *zptr)
{
int tempx = *xptr;
int tempy = *yptr;
int tempz = *zptr;
*yptr = tempx;
*zptr = tempy;
*xptr = tempz;
}
2
假设函数operate的部分C代码如下:
1 int operate(int x, int y, int z, int k)
2 {
3 int v = ___________________;
4 return v;
5 }
以下汇编用来实现第3行语句的功能,请写出每条汇编指令的注释,并根据以下汇编代码,填写operate函数缺失的部分。
1 movl 12(%ebp), %ecx
2 sall 8, %ecx
3 movl 8(%ebp), %eax
4 movl 20(%ebp), %edx
5 imull %edx, %eax
6 movl 16(%ebp), %edx
7 andl 65520, %edx
8 addl %ecx, %edx
9 subl %edx, %eax
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
int v = xk - (z&0xFFF0 + y256);
或
int v = x*k - (z&65520 + (y<<8));
或其他功能一样但表达稍有不同的语句。
1 movl 12(%ebp), %ecx //R[ecx]<-M[R[ebp]+12],将y送ECX
2 sall 8, %ecx //R[ecx]<-R[ecx]<<8,y*256送ECX
3 movl 8(%ebp), %eax //R[eax]<-M[R[ebp]+8],将x送EAX
4 movl 20(%ebp), %edx //R[edx]<-M[R[ebp]+20],将k送EDX
5 imull %edx, %eax //R[eax]<-R[eax]R[edx],将xk送EAX
6 movl 16(%ebp), %edx //R[edx]<-M[R[ebp]+16],将z送EDX
7 andl 65520, %edx //R[edx]<-R[edx]&65520,将z&65520送EDX
8 addl %ecx, %edx //R[edx]<-R[edx]+R[ecx],将z&65520+y*256送EDX
9 subl %edx, %eax //R[eax]<-R[eax]-R[edx],将xk-(z&65520+y256)送EAX
题目解析:
int v = xk - (z&0xFFF0 + y256);或int v = x*k - (z&65520 + (y<<8));或其他功能一样但表达稍有不同的语句。
1 movl 12(%ebp), %ecx //R[ecx]<-M[R[ebp]+12],将y送ECX
2 sall 8, %ecx //R[ecx]<-R[ecx]<<8,y*256送ECX
3 movl 8(%ebp), %eax //R[eax]<-M[R[ebp]+8],将x送EAX
4 movl 20(%ebp), %edx //R[edx]<-M[R[ebp]+20],将k送EDX
5 imull %edx, %eax //R[eax]<-R[eax]R[edx],将xk送EAX
6 movl 16(%ebp), %edx //R[edx]<-M[R[ebp]+16],将z送EDX
7 andl 65520, %edx //R[edx]<-R[edx]&65520,将z&65520送EDX
8 addl %ecx, %edx //R[edx]<-R[edx]+R[ecx],将z&65520+y*256送EDX
9 subl %edx, %eax //R[eax]<-R[eax]-R[edx],将xk-(z&65520+y256)送EAX
3
已知函数test的入口参数有a、b、c和p,C语言过程体代码如下:
*p = a;
return b*c;
函数test过程体对应的汇编代码如下:
1 movl 20(%ebp), %edx
2 movsbw 8(%ebp), %ax
3 movw %ax, (%edx)
4 movzwl 12(%ebp), %eax
5 movzwl 16(%ebp), %ecx
6 mull %ecx, %eax
写出函数test的原型,给出返回参数的类型以及入口参数a、b、c和p的类型和顺序。
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
unsigned int test(char a, unsigned short b, unsigned short c, shrot *p);
1)第3条指令对应的是*p=a,结合第2条可知a为第1个参数(4个参数偏移分别为20、8、12、16,最左边的参数偏移最小)且为char型(movsbw,将字节符号扩展到16位);
2)由第1、3条指令可知p为第4个参数,其类型为short *;
3)由第4和第6条指令(R[eax]<-R[eax]*R[ecx],eax在前对应b,ecx在后对应c)可知b为第2个参数,其类型为unsigned short(movzwl,16位零扩展到32位);
4)由第5和第6条指令可知c为第3个参数(偏移值16),其类型为unsigned short(原因同b)
5)第6条指令为2个无符号32位数相乘,其结果为32位无符号数,因此函数返回值为unsigned int
题目解析:
unsigned int test(char a, unsigned short b, unsigned short c, shrot *p);
1)第3条指令对应的是*p=a,结合第2条可知a为第1个参数(4个参数偏移分别为20、8、12、16,最左边的参数偏移最小)且为char型(movsbw,将字节符号扩展到16位);
2)由第1、3条指令可知p为第4个参数,其类型为short *;
3)由第4和第6条指令(R[eax]<-R[eax]*R[ecx],eax在前对应b,ecx在后对应c)可知b为第2个参数,其类型为unsigned short(movzwl,16位零扩展到32位);
4)由第5和第6条指令可知c为第3个参数(偏移值16),其类型为unsigned short(原因同b)
5)第6条指令为2个无符号32位数相乘,其结果为32位无符号数,因此函数返回值为unsigned int
4
已知函数func的C语言代码框架及其过程体对应的汇编代码如下所示,根据对应的汇编代码填写C代码中缺失的表达式。(jg的转移条件为SF=OF且ZF=0,带符号数A>B;jle的转移条件为SF!=OF或ZF=1,带符号数A<=B;jl的转移条件为SF!=OF且ZF=0,带符号数A<B)
int func (int x, int y)
{
int z = __________________;
if (_____________) {
if (_____________)
z = _______________;
else
z = _______________;
} else if (_____________)
z = _____________;
return z;
}
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
int func(int x, int y)
{
int z = x*y;
if (x <= -100) {
if (y > x)
z = x + y;
else
z = x - y;
} else if ( x >= 16)
z = x&y;
return z;
}
题目解析:
int func(int x, int y)
{
int z = x*y;
if (x <= -100) {
if (y > x)
z = x + y;
else
z = x - y;
} else if ( x >= 16)
z = x&y;
return z;}
5
已知函数f1的C语言代码框架及其过程体对应的汇编代码如下所示,根据对应的汇编代码填写C代码中缺失的部分,并说明函数f1的功能。(test根据两个操作数相“与”的结果来设置标志位,但不改变原操作数;je的跳转条件为ZF=1,即等于0;jne的跳转条件是ZF=0,即不等于0)
int f1(unsigned x)
{
int y = 0;
while(__________) {
________;
________;
}
return ________;
}
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
int f1(unsigned x)
{
int y = 0;
while(x != 0) {
y ^= x;
x >>= 1;
}
return y&0x1;
}
f1的功能是返回(x(x>>1)(x>>2)^...)&0x1,因此f1用于检测x的奇偶性,有奇数个1则返回1,否则返回0。
题目解析:
int f1(unsigned x)
{
int y = 0;
while(x != 0)
{
y ^= x;
x >>= 1;
}
return y&0x1;
}
f1的功能是返回(x(x>>1)(x>>2)^...)&0x1,因此f1用于检测x的奇偶性,有奇数个1则返回1,否则返回0。
6
已知函数sw的C语言代码框架如下:
int sw(int x){
int v = 0;
switch(x)
{//switch语句中的处理部分省略
}
return v;}
对函数sw进行编译,得到函数过程体中开始部分的汇编代码以及跳转表如下(ja的跳转条件是CF=0且ZF=0,即无符号整数A>B):
试回答进入.L2-.L7时x的取值。
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
由前4句代码可知x+3>7时进入L7分支,否则根据跳转表进行跳转,根据跳转表,x与跳转目标标号的关系为:
x+3=0: .L7
x+3=1: .L2
x+3=2: .L2
x+3=3: .L3
x+3=4: .L4
x+3=5: .L5
x+3=6: .L7
x+3=7: .L6
综上,x与跳转分支的关系为:
case -2:
case -1:
//跳转.L2
break;
case 0:
//跳转.L3
break;
case 1:
//跳转.L4
break;
case 2:
//跳转.L5
break;
case 4:
//跳转.L6
break;
default:
//跳转.L7
break;
题目解析:
由前4句代码可知x+3>7时进入L7分支,否则根据跳转表进行跳转,根据跳转表,x与跳转目标标号的关系为:
x+3=0: .L7
x+3=1: .L2
x+3=2: .L2
x+3=3: .L3
x+3=4: .L4
x+3=5: .L5
x+3=6: .L7
x+3=7: .L6
综上,x与跳转分支的关系为:
case -2:
case -1:
//跳转.L2
break;
case 0:
//跳转.L3
break;
case 1:
//跳转.L4
break;
case 2:
//跳转.L5
break;
case 4:
//跳转.L6
break;
default:
//跳转.L7
break;
7
已知函数funct的C语言代码如下:
include <stdio.h>
int funct(void)
{
int x, y;
scanf("%d,%d", &x, &y);
return x-y;
}
函数funct对应的汇编代码如下:
假设函数funct开始执行时,R[esp]=0xbc000020, R[ebp] = 0xbc000030, 指向字符串“%d %d”的指针为0x804c0000。试回答下列问题:
1)执行第3、10、13行的指令后,寄存器EBP中的内容分别是什么?
2)执行第3、10、13行的指令后,寄存器ESP中的内容分别是什么?
3)局部变量x和y所在存储单元的地址分别是什么?
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
每次执行pushl指令后,R[esp]=R[esp]-4;
第2行执行完后,R[esp]=0xbc00001c;
执行第3条指令后,R[ebp]=R[esp]=0xbc00001c;
执行第4条指令后,R[esp]=0xbbfffff4;
第5-9条指令不改变ESP和EBP
第10条指令执行scanf函数前,返回地址入栈,ESP变为0xbbfffff0,scanf执行完毕后,返回地址出栈,ESP变为0xbbfffff4;
第11-12条指令不改变ESP和EBP
执行第13条指令后,EBP和ESP的内容恢复为刚进入funct时的值0xbc000030和0xbc000020。
因此:
1)执行第3、10、13行的指令后,寄存器EBP中的内容分别是0xbc00001c、0xbc00001c、0xbc000030
2)执行第3、10、13行的指令后,寄存器ESP中的内容分别是0xbc00001c、0xbbfffff4、0xbc000020
3)由指令5-8可知x和y的地址分别为R[ebp]-4=0xbc000018、R[ebp]-8=0xbc000014
题目解析:
每次执行pushl指令后,R[esp]=R[esp]-4;
第2行执行完后,R[esp]=0xbc00001c;
执行第3条指令后,R[ebp]=R[esp]=0xbc00001c;
执行第4条指令后,R[esp]=0xbbfffff4;
第5-9条指令不改变ESP和EBP第10条指令执行scanf函数前,返回地址入栈,ESP变为0xbbfffff0,scanf执行完毕后,返回地址出栈,ESP变为0xbbfffff4;
第11-12条指令不改变ESP和EBP执行第13条指令后,EBP和ESP的内容恢复为刚进入funct时的值0xbc000030和0xbc000020。
因此:
1)执行第3、10、13行的指令后,寄存器EBP中的内容分别是0xbc00001c、0xbc00001c、0xbc000030
2)执行第3、10、13行的指令后,寄存器ESP中的内容分别是0xbc00001c、0xbbfffff4、0xbc000020
3)由指令5-8可知x和y的地址分别为R[ebp]-4=0xbc000018、R[ebp]-8=0xbc000014
假设函数sumij的C代码如下,其中M,N是用define声明的常数
1 int a[M][N], b[N][M];
2
3 int sumij(int i, int j) {
4 return a[i][j] + b[j][i];
5 }
已知函数sumij的过程体对应的汇编代码如下:
1 movl 8(%ebp), %ecx
2 movl 12(%ebp), %edx
3 leal (,%ecx, 8), %eax
4 subl %ecx, %eax
5 addl %edx, %eax
6 leal (%edx, %edx, 4), %edx
7 addl %ecx, %edx
8 movl a(, %eax, 4), %eax //a为数组a的首地址
9 addl b(,%edx, 4), %eax //b为数组b的首地址
根据上述汇编代码,确定M和N的值。
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
1 movl 8(%ebp), %ecx //R[ecx] = i
2 movl 12(%ebp), %edx //R[edx] = j
3 leal (,%ecx, 8), %eax //R[eax] = 8*i
4 subl %ecx, %eax //R[eax] = 8i - i = 7i
5 addl %edx, %eax //R[eax] = 7*i + j
6 leal (%edx, %edx, 4), %edx //R[edx] = 4j + j = 5j
7 addl %ecx, %edx //R[edx] = 5*j + i
8 movl a(, %eax, 4), %eax //R[eax] = M[a+74i + 4*j
9 addl b(,%edx, 4), %eax //R[eax] = M[a + 74i +4j] + M[b + 54j + 4i
由此可知,M=5,N=7
题目解析:
1 movl 8(%ebp), %ecx //R[ecx] = i
2 movl 12(%ebp), %edx //R[edx] = j
3 leal (,%ecx, 8), %eax //R[eax] = 8*i
4 subl %ecx, %eax //R[eax] = 8i - i = 7i
5 addl %edx, %eax //R[eax] = 7*i + j
6 leal (%edx, %edx, 4), %edx //R[edx] = 4j + j = 5j
7 addl %ecx, %edx //R[edx] = 5*j + i
8 movl a(, %eax, 4), %eax //R[eax] = M[a+74i + 4*j
9 addl b(,%edx, 4), %eax //R[eax] = M[a + 74i +4j] + M[b + 54j + 4i由此可知,M=5,N=7
2
假设结构体node的定义、函数np_init的C代码及其对应部分汇编代码如下:
struct node {
int *p;
struct {
int x; int y;
} s;
struct node *next;
};
void np_init(struct node *np){
np->s.x = ______________;
np->p = _______________;
np->next = ____________;
}
movl 8(%ebp), %eax
movl 8(%eax), %edx
movl %edx, 4(%eax)
leal 4(%eax), %edx
movl %edx, (%eax)
movl %eax, 12(%eax)
回答下列问题:
(1)结构node所需存储空间有多少字节?成员p、s.x、s.y、和next的偏移地址分别为多少?
(2)根据汇编代码填写np_init中缺失的表达式。
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
(1)p和next是地址,各占4字节,x和y各占4字节,总共16字节;成员p、s.x、s.y、和next的偏移地址分别为0、4、8、12。
(2)
movl 8(%ebp), %eax //R[eax] = np
movl 8(%eax), %edx //R[edx] = np->s.y
movl %edx, 4(%eax) //np->s.x = np->s.y
leal 4(%eax), %edx //R[edx] = np + 4
movl %edx, (%eax) //np->p = np + 4 = &(np->s.x)
movl %eax, 12(%eax) //np->nexp = np
因此缺失部分表达式如下:
void np_init(struct node *np){
np->s.x = np->s.y;
np->p = &(np->s.x);
np->next = np;
}
题目解析:
(1)p和next是地址,各占4字节,x和y各占4字节,总共16字节;成员p、s.x、s.y、和next的偏移地址分别为0、4、8、12。
(2)
movl 8(%ebp), %eax //R[eax] = np
movl 8(%eax), %edx //R[edx] = np->s.y
movl %edx, 4(%eax) //np->s.x = np->s.y
leal 4(%eax), %edx //R[edx] = np + 4
movl %edx, (%eax) //np->p = np + 4 = &(np->s.x)
movl %eax, 12(%eax) //np->nexp = np
因此缺失部分表达式如下:
void np_init(struct node *np){
np->s.x = np->s.y;
np->p = &(np->s.x);
np->next = np;
}
3
给出下列各个结构类型中每个成员的偏移量、结构总大小。
(1)struct S1 {short s; char c; int i; char d;};
(2)struct S2 {int i; short s; char c; char d;};
(3)struct S3 {char c; shrot s; int i; char d;};
(4)struct S4 {short s[3]; char c;};
(5)struct S5 {char c[3];short *s; int i; char d; double e;};
(6)struct S6 {struct S1 c[3];struct S2 *s;char d;};
要求:
1)图片上传(建议Chrome,可对图片复制粘贴)
2)图片方向正确
3)图片上有签名
回答:
参考答案:
(1)s、c、i、d的偏移量分别为0、2、4、8,总共12字节;
(2)i、s、c、d的偏移量分别为0、4、6、7,总共8字节;
(3)c、s、i、d的偏移量分别为0、2、4、8,总共12字节;
(4)s、c的偏移量分别为0、6,总共8字节;
(5)c、s、i、d、e的偏移量分别为0、4、8、12、16,总共24字节;
(6)c、s、d的偏移量分别为0、36、40,总共44字节。
题目解析:
(1)s、c、i、d的偏移量分别为0、2、4、8,总共12字节;
(2)i、s、c、d的偏移量分别为0、4、6、7,总共8字节;
(3)c、s、i、d的偏移量分别为0、2、4、8,总共12字节;
(4)s、c的偏移量分别为0、6,总共8字节;
(5)c、s、i、d、e的偏移量分别为0、4、8、12、16,总共24字节;(6)c、s、d的偏移量分别为0、36、40,总共44字节。