内容发布更新时间 : 2024/12/27 0:23:15星期一 下面是文章的全部内容请认真阅读。
表达式EXPR uptr->s1.x uptr->s1.y &uptr->s1.z uptr->s2.a uptr->s2.a[uptr->s2.b] *uptr->s2.p TYPE类型 int 汇编指令序列 movl (êx), êx movl êx, (íx)
27.给出下列各个结构类型中每个成员的偏移量、结构总大小以及在IA-32/Linux下结构起始位置的对齐要求。 (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; short 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;};
28.以下是结构test的声明:
struct { char c; double d;
int i;
short s;
char *p;
long l; long long g; void *v; } test;
假设在Windows平台上编译,则这个结构中每个成员的偏移量是多少?结构总大小为多少字节?如何调整成员的先后顺序使得结构所占空间最小?
29.以下是函数getline存在漏洞和问题的C语言代码实现,右边是其对应的反汇编部分结果:
char *getline() {
char buf[8]; char *result; gets(buf);
result=malloc(strlen(buf)); strcpy(result, buf); return result; }
1 0804840c
push mov sub mov mov mov lea mov call ?p
%esp, ?p $0x28, %esp
?x, -0xc(?p) %esi, -0x8(?p) íi, -0x4(?p) -0x14(?p), %esi %esi, (%esp) 80483c9
假定有一个调用过程P调用了函数getline,其返回地址为0x80485c8,为调用getline函数而执行完call指令
时,部分寄存器的内容如下:R[ebp]=0xbffc0800,R[esp]=0xbffc07f0,R[ebx]=0x5,R[esi]=0x10,R[edi]=0x8。执行程序时从标准输入读入的一行字符串为“0123456789ABCDEF0123456789A”,此时,程序会发生段错误(segmentation fault)并中止执行,经调试确认错误是在执行getline的ret指令时发生的。回答下列问题或完成下列任务。
(1)分别画出执行第7行和第10行汇编指令后栈中的信息存放情况。要求给出存储地址和存储内容,并指
出存储内容的含义(如返回地址、EBX旧值、局部变量、入口参数等)。
(2)当执行到getline的ret指令时,假如程序不发生段错误,则正确的返回地址是什么?发生段错误是因
为执行getline的ret指令时得到了什么样的返回地址? (3)执行完第10行汇编指令后,哪些寄存器的内容已被破坏?
(4)除了可能发生缓冲区溢出以外,getline的C代码还有哪些错误?
08 04 85 c8 返回P的地址 bf fc 08 00 EBP在P中旧值 00 00 00 08 00 00 00 10 00 00 00 05 被调用者保存寄存器在P中的旧值 buf[7]~ buf[4] buf[3]~ buf[0]
08 41 39 38 返回P的地址 37 36 35 34 EBP在P中旧值 33 32 31 30 46 45 44 43 42 41 39 38 37 36 35 34 buf[7]~ buf[4] 33 32 31 30 buf[3]~ buf[0]
被调用者保存寄存器在P中的旧值
EBP EBP ESP a) 执行第7行后的栈
ESP bf fc 07 d8 gets入口参数
b) 执行第10行后的栈
30.假定函数abc的入口参数有a、b和c,每个参数都可能是带符号整数类型或无符号整数类型,而且它们的长
度也可能不同。该函数具有如下过程体:
*b += c; *a += *b;
在x86-64机器上编译后的汇编代码如下:
1 abc: 2 addl (%rdx), íi 3 movl íi, (%rdx) 4 movslq íi, %rdi 5 addq %rdi, (%rsi) 6 ret
分析上述汇编代码,以确定三个入口参数的顺序和可能的数据类型,写出函数abc可能的4种合理的函数
原型。
31.函数lproc的过程体对应的汇编代码如下:
1 2 3 4
movl movl movl movl
8(?p), íx 12(?p), ìx $255, %esi
$-2147483648, íi
5 .L3: 6 movl íi, êx 7 andl íx, êx 8 xorl êx, %esi 9 movl ìx, ?x 10 shrl %bl, íi 11 testl íi, íi 12 jne .L3 13 movl %esi, êx
上述代码根据以下lproc函数的C代码编译生成: 1 2 3 4 5 6 7 8
int {
lproc(int x, int k)
int val = ; int i;
for (i= ; i ; i = ) { val ^= ; }
return val;
9 }
回答下列问题或完成下列任务。 (1)给每条汇编指令添加注释。
(2)参数x和k分别存放在哪个寄存器中?局部变量val和i分别存放在哪个寄存器中? (3)局部变量val和i的初始值分别是什么? (4)循环终止条件是什么?循环控制变量i是如何被修改的? (5)填写C代码中的缺失部分。
32.假设你需要维护一个大型C语言程序,其部分代码如下:
1 typedef struct { 2 unsigned l_data; 3 line_struct x[LEN]; 4 unsigned r_data; 5 } str_type; 6 7 void proc(int i, str_type *sptr) { 8 unsigned val = sptr->l_data + sptr->r_data; 9 line_struct *xptr = &sptr->x[i]; 10 xptr->a[xptr->idx] = val; 11 }
编译时常量LEN以及结构类型line_struct的声明都在一个你无权访问的文件中,但是,你有代码的.o版本
(可重定位目标)文件,通过OBJDUMP 反汇编该文件后,得到函数proc对应的反汇编结果如下,根据反汇编结果推断常量LEN的值以及结构类型line_struct的完整声明(假设其中只有成员a和idx)。
1 00000000
push mov push mov mov imul lea sub add mov add mov pop pop ret
?p
%esp, ?p ?x
0x8(?p), êx 0xc(?p), ìx $0x1c, êx, ?x 0x0(, êx, 8), íx êx, íx
0x4(ìx, ?x, 1), íx 0xc8(ìx), êx (ìx), êx
êx, 0x8(ìx, íx, 4) ?x ?p
33.假设嵌套的联合数据类型node声明如下: 1 union node { 2 struct { 3 int *ptr; 4 int data1; 5 } n1; 6 struct { 7 int data2; 8 union node *next; 9 } n2; 10 }; 有一个进行链表处理的过程chain_proc的部分C代码如下:
1 void chain_proc(union node *uptr) {
2 uptr-> = *(uptr-> ) – uptr-> ; 3 }
过程chain_proc的过程体对应的汇编代码如下: 1 movl 8(?p), íx 2 movl 4(íx), ìx 3 movl (ìx), êx 4 movl (êx), êx 5 subl (íx), êx 6 movl êx, 4(ìx)
回答下列问题或完成下列任务。
(1)node类型中结构成员n1.ptr、n1.data1、n2.data2、n2.next的偏移量分别是多少? (2)node类型总大小占多少字节?
(3)根据汇编代码写出chain_proc的C代码中缺失的表达式。
34.以下声明用于构建一棵二叉树: 1 typedef struct TREE *tree_ptr; 2 struct TREE { 3 tree_ptr left; 4 tree_ptr right; 5 long val;
6 } ; 有一个进行二叉树处理的函数trace的原型为“long trace( tree_ptr tptr) ;”,其过程体对应的x86-64汇编代
码(64位版本)如下: 1 trace: 2 movl $0, êx 3 testq %rdi, %rdi 4 je .L2 5 .L3: 6 movq 16(%rdi), %rax 7 movq (%rdi), %rdi 8 testq %rdi, %rdi 9 jne .L3 10 .L2: 11 rep //在此相当于空操作指令,避免使ret指令作为跳转目的指令 12 ret
回答下列问题或完成下列任务。
(1)函数trace的入口参数tptr通过哪个寄存器传递? (2)写出函数trace完整的C语言代码。 (3)说明函数trace的功能。