20155212 2017-2018-1 《信息安全系统设计》第8周课下作业
题目1
- 完成家庭作业4.47,4.48,4.49
- 相应代码反汇编成X86-64汇编
- 把上述X86-64汇编翻译成Y86汇编,并给出相应机器码
- 发操作过程、测试、问题解决过程博客链接
4.47
A. 书写并测试一个C版本,用指针引用数组元素,而不是用数组索引。
- 用指针引用数组元素:
#include <stdio.h>
/*Bubble sorts:Pointer version*/
void bubble_p(long *data,int count){
long i, last, t;
for(last = count-1; last > 0; last--){
for(i = 0; i < last; i++){
if(*(data+i+1)<*(data+i)){
t = *(data+i+1);
*(data+i+1) = *(data+i);
*(data+i) = t;
}
}
}
}
void main(){
int i;
long data[5]={4, 1, 0, 2, 3};
bubble_p(data, 5);
for(i=0; i<5; i++)
{
printf("%ld ", *(data+i));
}
printf("
");
}
- 运行结果
B. 书写并测试这个函数和测试代码组成的Y86-64程序。
- 使用
gcc -E Bubble.c -Og -o Bubble1.i
、gcc -S Bubble.c -Og -o Bubble1.s
编译代码,这样生成符合原始C代码整体结构的机器代码的优化等级,便于理解。 - X86-64汇编代码
bubble_p:
leal -1(%rsi), %r9d
movslq %r9d, %r9
jmp .L2
.L4:
leaq 8(%rdi,%rax,8), %rsi
movq (%rsi), %rcx
leaq (%rdi,%rax,8), %rdx
movq (%rdx), %r8
cmpq %r8, %rcx
jge .L3
movq %r8, (%rsi)
movq %rcx, (%rdx)
.L3:
addq $1, %rax
jmp .L5
.L6:
movl $0, %eax
.L5:
cmpq %r9, %rax
jl .L4
subq $1, %r9
.L2:
testq %r9, %r9
jg .L6
rep ret
.LC0:
main:
pushq %rbx
subq $48, %rsp
movq %fs:40, %rax
movq %rax, 40(%rsp)
xorl %eax, %eax
movq $4, (%rsp)
movq $1, 8(%rsp)
movq $0, 16(%rsp)
movq $2, 24(%rsp)
movq $3, 32(%rsp)
movl $5, %esi
movq %rsp, %rdi
call bubble_p
movl $0, %ebx
jmp .L8
.L9:
movslq %ebx, %rax
movq (%rsp,%rax,8), %rdx
movl $.LC0, %esi
movl $1, %edi
movl $0, %eax
call __printf_chk
addl $1, %ebx
.L8:
cmpl $4, %ebx
jle .L9
movl $10, %edi
call putchar
movq 40(%rsp), %rax
xorq %fs:40, %rax
je .L10
call __stack_chk_fail
.L10:
addq $48, %rsp
popq %rbx
ret
- Y86-64代码
.pos 0
irmovq stack,%rsp
call main
halt
bubble_p:
irmovq $1, %r8
subq %r8, %rsi
rrmovq %rsi, %r9
rrmovq %r9, %r9
jmp .L2
.L4:
addq %rax, %rax
addq %rax, %rax
addq %rax, %rax
addq %rdi, %rax
irmovq $8, %r10
addq %r10, %rax
rrmovq %rax, %rsi
mrmovq (%rsi), %rcx
rrmovq %rax, %r8
addq %r8, %r8
addq %r8, %r8
addq %r8, %r8
addq %rdi, %r8
rrmovq %r8, %rdx
mrmovq (%rdx), %r8
rrmovq %rcx, %r10
subq %r8, %r10
jge .L3
rmmovq %r8, (%rsi)
rmmovq %rcx, (%rdx)
.L3:
irmovq $1, %r8
addq %r8, %rax
jmp .L5
.L6:
irmovq $0, %r8
rrmovq %r8, %rax
.L5:
rrmovq %rax, %r10
subq %r9, %r10
.L2:
jg .L6
ret
main:
pushq %rbp
irmovq $48, %r8
rrmovq %r8, %rsp
xorq %rax, %rax
irmovq $4, %r8
rmmovq %r8, (%rbp)
irmovq $1, %r8
rmmovq %r8, 8(%rbp)
irmovq $0, %r8
rmmovq %r8, 16(%rbp)
irmovq $2, %r8
rmmovq %r8, 24(%rbp)
irmovq $3, %r8
rmmovq %r8, 32(%rbp)
irmovq $5, %r8
rrmovq %r8, %rsi
rrmovq %rsp, %rdi
call bubble_p
irmovq $0, %r9
rrmovq %r9 ,%rbx
jmp .L8
.L9:
rrmovq %rbx, %rax
rrmovq %rax, %r8
addq %r8, %r8
addq %r8, %r8
addq %r8, %r8
addq %rsp, %r8
rrmovq %r8, %rdx
irmovq $1, %r10
rrmovq %r10, %rdi
irmovq $0, %r8
rrmovq %r8, %rax
call _printf_chk
rrmovq %r10, %rbx
.L8:
irmovq $4, %rbx
jle .L9
irmovq $10, %rdi
call putchar
mrmovq 40(%rsp), %rax
je .L10
call _stack_chk_fail
.L10:
irmovq $48, %r8
addq %r8, %rsp
popq %rbx
ret
.pos 0x200
stack:
- 主要修改内容
leaq
:要与``movq```类区分开movq
:要根据源和目的的类型划分为不同的四种命令addq
类:必须是寄存器之间才能操作cmpq
:将第二操作数放到新寄存器,然后subq
4.48
- 不使用跳转,最多使用3次条件传送
- 代码#include <stdio.h> /*Bubble sorts:Pointer version*/ void bubble_p(long *data,int count){ long i, last, t; for(last = count-1; last > 0; last--){ for(i = 0; i < last; i++){ if(*(data+i+1)<*(data+i)){ t = *(data+i)-*(data+i+1); if(t>0){ t = *(data+i); *(data+i) = *(data+i+1); *(data+i+1) = t; } } } } } void main(){ int i; long data[5]={4, 1, 0, 2, 3}; bubble_p(data, 5); for(i=0; i<5; i++) { printf("%ld ", *(data+i)); } printf(" "); }
- 分析:通过“t=(data+i)-(data+i+1)”来设置条件码,通过comvg条件传送指令实现if(t>0)中的三个赋值语句
4.48
-
不使用跳转,最多使用1次条件传送
- 代码
#include <stdio.h> #include <stack> using namespace std; /*Bubble sorts:Pointer version*/ void bubble_p(long *data, int count) { long i, last, t; stack <long> S; for (last = count - 1; last > 0; last--) { for (i = 0; i < last; i++) { if (*(data + i + 1)<*(data + i)) { t = *(data + i) - *(data + i + 1); if (t>0) { S.push(*(data+i+1)); *(data + i + 1) = *(data+i); *(data + i) = S.top(); S.pop(); } } } } } void main() { int i; long data[5] = { 4, 1, 0, 2, 3 }; bubble_p(data, 5); for (i = 0; i<5; i++) { printf("%ld ", *(data + i)); } printf(" "); }
- 分析:使用栈。这里我调用了stack库。
题目2
把课上练习3的daytime服务器分别用多进程和多线程实现成并发服务器并测试
基于socket 使用教材的csapp.h, csapp.c
实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
服务器响应消息格式是
“
客户端IP:XXXX
服务器实现者学号:XXXXXXXX
当前时间: XX:XX:XX
”
提交一个客户端至少查询三次时间的截图测试截图
提交至少两个客户端查询时间的截图测试截图
-
Daytime
DAYTIME协议是基于TCP的应用,是一种有用的调试工具,它的作用是返回当前时间和日期,格式是字符串格式。
- 基于TCP的daytime服务:daytime服务是基于TCP的应用,服务器在TCP端口13侦听,一旦有连接建立就返回ASCII形式的日期和时间,在传送完后关闭连接。接收到的数据被忽略。
- 基于UDP的daytime服务:daytime服务也可以使用UDP协议,它的端口也是13,不过UDP是用数据报传送当前时间的。接收到的数据被忽略。
- Daytime格式:Weekday, Month Day, Year Time-Zone
-
使用
man -k time | grep 2
查看系统调用 -
使用
man 2 time
查看time()
-
查看
localtime()
-
tm
结构体struct tm { int tm_sec; /* Seconds (0-60) */ int tm_min; /* Minutes (0-59) */ int tm_hour; /* Hours (0-23) */ int tm_mday; /* Day of the month (1-31) */ int tm_mon; /* Month (0-11) */ int tm_year; /* Year - 1900 */ int tm_wday; /* Day of the week (0-6, Sunday = 0) */ int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ int tm_isdst; /* Daylight saving time */ };
-
多线程结果
-
多进程结果