(1)给每条汇编指令添加注释,并说明每条指令执行后,目的寄存器中存放的是什么信息? (2)上述函数过程体中用到了哪些被调用者保存寄存器和哪些调用者保存寄存器?在该函数过程体前面的准备
阶段哪些寄存器必须保存到栈中?
(3)为什么第7行中的DX寄存器需要算术右移15位?
15.已知函数f1的C语言代码框架及其过程体对应的汇编代码如下,根据对应的汇编代码填写C代码中缺失部分,
并说明函数f1的功能。
1 int f1(unsigned x) 2 { 3 int y = 0 ; 4 5 6 7 while ( ) { } return ; ; 1 movl 8(?p), íx 2 movl $0, êx 3 testl íx, íx 4 je .L1 5 .L2: 6 xorl íx, êx 7 shrl $1, íx 8 jne .L2 9 .L1:
10 andl $1, êx
8 }
16.已知函数sw的C语言代码框架如下:
int sw(int x) { int v=0; switch (x) { /* switch语句中的处理部分省略 */
}
return v; }
对函数sw进行编译,得到函数过程体中开始部分的汇编代码以及跳转表如下:
1 movl 8(?p), êx 2 addl $3, êx 3 cmpl $7, êx 4 ja .L7
5 jmp *.L8( , êx, 4) 6 .L7: 7 …… 8 ……
1 .L8: 2 .long 3 .long 4 .long 5 .long 6 .long 7 .long 8 .long 9 .long
.L7
.L2 .L2 .L3 .L4 .L5 .L7 .L6
回答下列问题:函数sw中的switch语句处理部分标号的取值情况如何?标号的取值在什么情况下执行default
分支?哪些标号的取值会执行同一个case分支?
17.已知函数test的入口参数有a、b、c和p,C语言过程体代码如下: *p = a; return b*c;
函数test过程体对应的汇编代码如下:
1 2
movl 20(?p), íx movsbw 8(?p), %ax
3 movw %ax, (íx)
4 movzwl 12(?p), êx 5 movzwl 16(?p), ìx 6 mull ìx, êx
写出函数test的原型,给出返回参数的类型以及入口参数a、b、c和p的类型和顺序。
18.已知函数funct的C语言代码如下:
1 int funct(viod) { 2 int x, y; 3 scanf(“%x %x”, &x, &y); 4 return x-y; 5 }
函数funct对应的汇编代码如下: 1 funct: 2 3 4 5 6 7 8 9 10
push l movl subl leal movl leal movl movl call
?p
%esp, ?p $40, %esp
-8(?p), êx êx, 8(%esp) -4(?p), êx êx, 4(%esp) $.LC0, (%esp) scanf
//将指向字符串“%x %x”的指针入栈 //假定scanf执行后x=15,y=20
11 movl -4(?p), êx 12 subl -8(?p), êx 13 leave 14 ret
假设函数funct开始执行时,R[esp]=0xbc000020,R[ebp]=0xbc000030,执行第10行call指令后,scanf从标准输入读入的值为0x16和0x100,指向字符串“%x %x”的指针为0x804c000。回答下列问题或完成下列任务。 (1)执行第3、10和13行的指令后,寄存器EBP中的内容分别是什么? (2)执行第3、10和13行的指令后,寄存器ESP中的内容分别是什么? (3)局部变量x和y所在存储单元的地址分别是什么?
(4)画出执行第10行指令后funct的栈帧,指出栈帧中的内容及其地址。
19.已知递归函数refunc的C语言代码框架如下:
1 2 3 4 5 6
int refunc(unsigned x) { if ( ) return ; unsigned nx = ; int rv = refunc(nx) ; return ;
7 }
上述递归函数过程体对应的汇编代码如下:
1
movl
8(?p), ?x
2 movl $0, êx 3 testl ?x, ?x 4 je .L2 5 movl ?x, êx 6 shrl $1, êx 7 movl êx, (%esp) 8 call refunc 9 movl ?x, íx 10 andl $1, íx 11 leal (íx, êx), êx 12 .L2: …… ret
根据对应的汇编代码填写C代码中缺失部分,并说明函数的功能。
20.填写表3.14,说明每个数组的元素大小、整个数组的大小以及第i个元素的地址。
表3.14 题20用表 数组 char A[10] int B[100] short *C[5] short **D[6] long double E[10] long double *F[10] 元素大小(B) 数组大小(B) 起始地址 &A[0] &B[0] &C[0] &D[0] &E[0] &F[0] 元素i的地址
21.假设short型数组S的首地址AS和数组下标(索引)变量i(int型)分别存放在寄存器EDX和ECX中,下列
给出的表达式的结果存放在EAX或AX中,仿照例子填写表3.15,说明表达式的类型、值和相应的汇编代码。
表3.15 题21用表 表达式 S S+i S[i] &S[10] &S[i+2] &S[i]-S S[4*i+4] *(S+i-2) 类型 short short * 值 M[AS+2*i] AS+2*i+4 movw (íx, ìx, 2), %ax leal 4(íx, ìx, 2), êx 汇编代码
22.假设函数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(?p), ìx 2 movl 12(?p), íx 3 leal (,ìx, 8), êx 4 subl ìx, êx 5 addl íx, êx 6 leal (íx, íx, 4), íx 7 addl ìx, íx 8 movl a(, êx, 4), êx 9 addl b(,íx, 4), êx
根据上述汇编代码,确定M和N的值。
23.假设函数st_ele的C代码如下,其中,L、M和N是用#define声明的常数。
1 int a[L][M][N]; 2
3 int st_ele(int i, int j, int k, int *dst) { 4 *dst = a[i][j][k]; 5 return sizeof(a); 6 }
已知函数st_ele的过程体对应的汇编代码如下: 1 movl 8(?p), ìx 2 movl 12(?p), íx 3 leal (íx,íx, 8), íx 4 movl ìx, êx 5 sall $6, êx 6 subl ìx, êx 7 addl êx, íx 8 addl 16(?p), íx 9 movl a(, íx, 4), êx 10 movl 20(?p), íx 11 movl êx, (íx) 12 movl $4536, êx
根据上述汇编代码,确定L、M和N的值。
24.假设函数trans_matrix的C代码如下,其中,M是用#define声明的常数。
1 void trans_matrix(int a[M][M]) { 2 int i, j, t; 3 for (i = 0; i < M; i++) 4 for (j = 0; j < M; j++) { 5 t = a[i][j]; 6 a[i][j] = a[j][i]; 7 a[j][i] = t; 8 } 9 }
已知采用优化编译(选项-O2)后函数trans_matrix的内循环对应的汇编代码如下: 1 .L2: 2 movl (?x), êx 3 movl (%esi, ìx, 4), íx 4 movl êx, (%esi, ìx, 4) 5 addl $1, ìx 6 movl íx, (?x) 7 addl $76, ?x 8 cmpl íi, ìx 9 jl .L2
根据上述汇编代码,回答下列问题或完成下列任务。
(1)M的值是多少?常数M和变量j分别存放在哪个寄存器中? (2)写出上述优化汇编代码对应的函数trans_matrix的C代码。
25.假设结构类型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(?p), êx movl 8(êx), íx movl íx, 4(êx) leal 4(êx), íx movl íx, (êx) movl êx, 12(êx)
回答下列问题或完成下列任务。
(1)结构node所需存储空间有多少字节?成员p、s.x、s.y和next的偏移地址分别
为多少?
(2)根据汇编代码填写np_init中缺失的表达式。
26.假设联合类型utype的定义如下: typedef union { struct { int x; short y; short z; } s1 struct { short a[2]; int b;
char *p;
} s2 } utype;
若存在具有如下形式的一组函数:
viod getvalue(utype *uptr, TYPE *dst) { *dst = EXPR;
}
该组函数用于计算不同表达式EXPR的值,返回值的数据类型根据表达式的类型确定。假设函数getvalue的入口参数uptr和dst分别被装入寄存器EAX和EDX中,仿照例子填写下表,说明在不同的表达式下的TYPE类型以及表达式对应的汇编指令序列(要求尽量只用EAX和EDX,不够用时再使用ECX)。