第三章习题-ddg 下载本文

表达式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 : 2 804840c: 55 3 804840d: 89 e5 4 804840f: 83 ec 28 5 8048412: 89 5d f4 6 8048415: 89 75 f8 7 8048418: 89 7d fc 8 804841b: 8d 75 ec 9 804841e: 89 34 24 10 8048421: e8 a3 ff ff ff

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 : 2 0: 55 3 1: 89 e5 4 3: 53 5 4: 8b 45 08 6 7: 8b 4d 0c 7 a: 6b d8 1c 8 d: 8d 14 c5 00 00 00 00 9 14: 29 c2 10 16: 03 54 19 04 11 1a: 8b 81 c8 00 00 00 12 20: 03 01 13 22: 89 44 91 08 14 26: 5b 15 27: 5d 16 28: c3

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的功能。