鲸鱼的抽屉  

2017-2018-1 20155312 《信息安全系统设计基础》第八周学习总结

教材学习内容总结

网络编程、并发编程

课堂实践

在这次课堂实践的前一天,我按照以下步骤为虚拟机分配共享数据空间:

  1. 在虚拟机的设置里设定一个本地主机的文件夹vboxshare作为共享文件夹
  2. 启动Ubuntu,打开终端窗口
    输入命令“sudo mkdir /mnt/shared”回车后键入密码
  3. 输入命令“sudo mount –t vboxsf vboxshare /mnt/shared"
  4. 输入命令“sudo gedit /etc/fstab”
    在弹出的文本末尾添加:
    “vboxshare /mnt/shared vboxsf rw,gid=100,uid=1000,auto 0 0”

结果没有共享成功,关闭虚拟机再打开时进入了“welcome to emergency code”无法进入图形化界面。

我第一个想到可能是因为我修改了系统文件/etc/fastab,可能改回去就好了,但是周二晚上我输入vi /etc/fastab时提示server什么的,总之就是进不去,心态崩了。然后试了各种方法,比如alt+ctrl+f7;startx;alt+ctrl+f1+f6;alt+f7;alt+ctrl+shift+f7;init 5;init3;删除X11中的配置文件“rm /etc/X11/xorg.conf”……总之都是徒劳。

最后尝试了一通,我选择重装一个虚拟机,但是更新系统更新到凌晨,也没有更新完,更别提安装vim等必备软件了。

修复虚拟机

借备用电脑熬过了课堂实践,我终于再次抱着试一试的心态去解决这个问题,开机后依旧显示“GIVE root password for maintenance (or type control-D to continue): ……”,首先输入“vi /etc/fstab”尝试改回自己修改了的系统文件,神奇的是这一次进去了!接着用dd 删除刚刚添加的那行“vboxshare /mnt/shared vboxsf rw,gid=100,uid=1000,auto 0 0”,准备保存时,发现无法输入wq保存,这是因为在这种模式下是没有写权限的,需要输入“mount / -o remount”挂载root权限,然后就可以编辑修改/etc/fastab文件了,最后输入reboot。重启一下就好了。

系统快照

根据这段经历,我第一次意识到了备份、快照的重要性(真的是只有虚拟机坏了才会意识到备份有多么重要)。所以准备研究一下怎么弄系统快照,其实很简单,步骤如下:

首先打开virtualbox后选择想要备份的虚拟机,点击右上角的"备份[系统快照]",然后输入备份名称和描述,等几秒钟就备份完成了,创建完毕后可以在主界面看到创建的快照极其相关信息,如下图所示:

当我们虚拟机出现了问题,我们可以选择“恢复备份”,回到备份状态;如果想要删除这个备份,可以点击删除备份。关机时,系统还会提示我们是否恢复备份,一般情况下我们忽略掉它就好。

任务一

4.47

A :修改代码用指针索引数组而不是数组,并添加了测试代码如下:

 1 #include<stdio.h>
  2 
  3 void bubble_a(long *data,long count)
  4 {
  5     long i,last,t;
  6     for(last = count-1;last>0;last--)
  7     {
  8         for(i = 0;i<last;i++)
  9         {
 10             if(*(data+i+1)<*(data+i))
 11             {
 12                 t=*(data+i+1);
 13                 *(data+i+1)=*(data+i);
 14                 *(data+i)=t;
 15             }
 16         }
 17     }
 18 }
 19 int main()
 20 {
 21     int i;
 22     long data[10] = {2,3,4,5,6,7,8,9,0,1};
 23     bubble_a(data,10);
 24     for(i=0;i<10;i++)
 25     {
 26         printf("%d\n",*(data+i));
 27     }
 28     return 0;
 29 }

运行后没有问题,可以实现升序排列:

B:接着先利用objdump -d 1来查看可执行文件的反汇编代码,依次输入以下指令查看汇编代码:

gcc -E paixu1.c -o paixu1.i
gcc-S paixu1.i -o paixu1.s
vi paixu1.s

然后删除“.”开头的注释部分,留下的汇编代码如下:

  1 bubble_a:
  2     pushq   %rbp
  3     movq    %rsp, %rbp
  4     movq    %rdi, -40(%rbp)
  5     movq    %rsi, -48(%rbp)
  6     movq    -48(%rbp), %rax
  7     subq    $1, %rax
  8     movq    %rax, -16(%rbp)
  9     jmp .L2 
 10 .L6:
 11     movq    $0, -24(%rbp)
 12     jmp .L3 
 13 .L5:
 14     movq    -24(%rbp), %rax
 15     addq    $1, %rax
 16     leaq    0(,%rax,8), %rdx
 17     movq    -40(%rbp), %rax
 18     addq    %rdx, %rax 
 19     movq    (%rax), %rdx
 20     movq    -24(%rbp), %rax
 21     leaq    0(,%rax,8), %rcx
 22     movq    -40(%rbp), %rax
 23     addq    %rcx, %rax 
 24     movq    (%rax), %rax
 25     cmpq    %rax, %rdx
 26     jge .L4 
 27     movq    -24(%rbp), %rax
 28     addq    $1, %rax
 29     leaq    0(,%rax,8), %rdx
 30     movq    -40(%rbp), %rax
 31     addq    %rdx, %rax 
 32     movq    (%rax), %rax
 33     movq    %rax, -8(%rbp)
 34     movq    -24(%rbp), %rax
 35     addq    $1, %rax
36     leaq    0(,%rax,8), %rdx
 37     movq    -40(%rbp), %rax
 38     addq    %rax, %rdx
 39     movq    -24(%rbp), %rax
 40     leaq    0(,%rax,8), %rcx
 41     movq    -40(%rbp), %rax
 42     addq    %rcx, %rax
 43     movq    (%rax), %rax
 44     movq    %rax, (%rdx)
 45     movq    -24(%rbp), %rax
 46     leaq    0(,%rax,8), %rdx
 47     movq    -40(%rbp), %rax
 48     addq    %rax, %rdx
 49     movq    -8(%rbp), %rax
 50     movq    %rax, (%rdx)
 51 .L4:
 52     addq    $1, -24(%rbp)
 53 .L3:
 54     movq    -24(%rbp), %rax
 55     cmpq    -16(%rbp), %rax
 56     jl  .L5
 57     subq    $1, -16(%rbp)
 58 .L2:
 59     cmpq    $0, -16(%rbp)
 60     jg  .L6
 61     nop
 62     popq    %rbp
 63     ret
 64 .LFE0:
 65 .LC0:
 66 main:
 67 .LFB1:
 68     pushq   %rbp
 69     movq    %rsp, %rbp
 70     subq    $112, %rsp
 71     movq    %fs:40, %rax
 72     movq    %rax, -8(%rbp)
 73     xorl    %eax, %eax
 74     movq    $2, -96(%rbp)
 75     movq    $3, -88(%rbp)
 76     movq    $4, -80(%rbp)
 77     movq    $5, -72(%rbp)
 78     movq    $6, -64(%rbp)
 79     movq    $7, -56(%rbp)
 80     movq    $8, -48(%rbp)
 81     movq    $9, -40(%rbp)
 82     movq    $0, -32(%rbp)
 83     movq    $1, -24(%rbp)
 84     leaq    -96(%rbp), %rax
 85     movl    $10, %esi
 86     movq    %rax, %rdi
 87     call    bubble_a
 88     movl    $0, -100(%rbp)
 89     jmp .L8
 90 .L9:
 91     movl    -100(%rbp), %eax
 92     cltq
 93     leaq    0(,%rax,8), %rdx
 94     leaq    -96(%rbp), %rax
 95     addq    %rdx, %rax
 96     movq    (%rax), %rax
 97     movq    %rax, %rsi
 98     movl    $.LC0, %edi
 99     movl    $0, %eax
100     call    printf
101     addl    $1, -100(%rbp)
102 .L8:
103     cmpl    $9, -100(%rbp)
104     jle .L9
105     movl    $0, %eax
106     movq    -8(%rbp), %rcx
107     xorq    %fs:40, %rcx
108     je  .L11
109     call    __stack_chk_fail
110 .L11:
111     leave
112     ret
113 .LFE1:

书写Y86-64汇编指令时有几点需要注意:

  1. Y86-64中要把movq指令转换为具体的rrmovq,rmmovq,mrmovq指令;
  2. Y86-64中OPq只对寄存器数据进行操作,可以借用%r8-%r14这些寄存器,先用“irmovq”指令将立即数放入寄存器中,再进行相关计算;
  3. Y86-64中没有加载有效地址指令leaq,需要用“addq”等指令来代替其功能;
  4. Y86-64中没有比较指令“cmpq”,可以用两个寄存器存放操作数的值然后用subq命令使两数相减来设置条件码;
  5. Y86-64中没有乘指令mulq,需要用addq来替换;
  6. 第71行的“movq %fs:40, %rax”指令,需要弄清楚%fs:40的含义和类型;
  7. 由于Y86-64指令集中所以操作都以8个字节为单位,所以在转换“movl,addl”这些四字节指令时要额外注意,有时需要保护高四字节的值,例如:
  • movl $0,-100(%rbp) 可以用以下指令代替:
143     irmovq  0xffffffff00000000,%r8
144     mrmovq  -100(%rbp),%r9  #取8字节的内存单元-100(%rbp) 的值
145     andq    %r8,%r9  #给低四个字节置0,高四个字节不变
146     rmmovq  %r9, -100(%rbp) 
  • cmpl $9, -100(%rbp)可以用以下指令代替:
161     mrmovq  -100(%rbp),%r9  #r9中是8字节的-100(%rbp)内存单元的值
162     irmovq  0xffffffff,%r8
163     andq    %r8,%r9  #保留r9低四个字节的值
164     irmovq  $9,%r10
165     subq    %r10,%r9  #用sub指令来设置条件码
  • movl $10, %esi:这里要注意movl在以寄存器作为目的时,会把寄存器的高位设为0 所以,无需保护高四字节的值,如以下指令所示:
140     irmovq  $10,%r9
141     rrmovq  %r9,%rsi
  • addl $1, -100(%rbp)可以用如下指令进行替换:
170     mrmovq  -100(%rbp),%r8  #r8为8字节的内存单元-100(%rbp)的值
171     irmovq  0xffffffff,%r9
172     irmovq  $1,%r10
173     addq    %r8,%r10  #先用八字节的数加1,结果放入r10
174     andq    %r9,%r10  #只保留低四字节的值
175     irmovq  0xffffffff00000000,%r11
176     andq    %r8,%r11  #将内存单元中低四字节置0存入r11
177     addq    %r11,%r10  #与刚才的和相加,结果原高四字节不变,低四字节加一
178     rmmovq  %r10,-100(%rbp)
  1. cltq指令:用于把%eax符号扩展到%rax,所以要先判断%eax的符号位,再决定给高四个字节置1还是0;
  2. Y86-64指令集中没有leave指令,要用“rrmovq %rbp,%rsp”+“popq %rbp”来代替。

但是,把初步编写的paixu1.ys文件拷贝到sim/y86-code里,并通过“make paixu.yo”生成y86-64编码时,提示出现了很多错误,如下图所示:

参照y86-code文件夹中的正确代码asum.ys,我有几个疑问:

  1. 为什么这里用了四字节指令?教材P245页写了Y86-64指令集只包括8字节整数操作,这里如何解释?
  2. 为什么asum.ys可以利用make指令生成.yo文件,但是教材P252图4-7中的代码却不可以,运行make指令时同样会报错,如下所示:

  1. Y86-64是如何处理位运算和字节扩展运算的?它就只有addq,subq,andq,xorq四种运算而没有乘除运算吗?那如果这样怎么利用四种运算实现大整数乘法呢?

通过在网上搜索,和询问周边同学,我没能找到答案。但是阅读了卢肖明学长第六周学习总结后,我发现Y86-64指令集和Y86指令集是不同的,Y86操作指令是4字节的,所以会出现以l为结尾的指令,自己下载的Y86模拟器应用在Y86指令集的基础上,与我们正在学习的Y86-64不匹配,所以即使输入书中原代码,也不会make成功。

重新下载老师在蓝墨云中提供的y86-84模拟器,删除原来的y86模拟器。

构建YIS步骤

参考老师的给出的实验楼资源,重新构建YIS,步骤如下:

  1. cd ~/Code/shiyanlou_cs413
  2. wget http://labfile.oss.aliyuncs.com/courses/413/sim.tar
  3. tar -xvf sim.tar
  4. cd sim
  5. sudo apt-get install bison flex tk
  6. sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so /usr/lib/libtk.so
  7. sudo ln -s /usr/lib/x86_64-linux-gnu/libtcl8.6.so /usr/lib/libtcl.so
  8. make

测试YIS步骤如下:

  1. cd y86-code
  2. 进入测试代码,教材p239页代码为asuml.ys,可以通过make asuml.yo进行汇编,asuml.yo就是汇编后的结果,见教材p238。
  3. make all可以汇编运行所有代码结果
修正Y86-64汇编代码的错误

ma在刚在新下载的sim文件夹中make一下,查看生成的yo文件。这次试用新的模拟器,再对paixu1.ys反汇编一下,发现错误少了不少,我将其归为四类:

  1. %fs:40看样子不是普通的寄存器,通过冒号我们可以想到这%fs:应该是在指明段。将117行改成irmovq、mrmovq,194行用寄存器中转一下试试;
  2. 真正的Y86-64是没有%eax寄存器的,这里忘了把它改成%rax;
  3. 前面已经转换了这句addl,忘记删掉原句了;
  4. y86-64中没有设计具体的系统异常处理模块,所以不会识别这里的堆栈错误处理模块。

修改后再次运行“make paixu1.yo”,还是出现了两类错误:

  1. %fs:40的含义还是没有理解,通过查询资料,我得知FS是x86-64中附加段寄存器(Extra Segment Register),其值为附加数据段的段值,但是y86-64没有这种加段超越前缀的寻址方式,而且貌似也没有这个附加数据段寄存器。“40”像个内存地址,因为加段超越前缀访问内存单元的方式一般是段超越前缀+地址;
  2. y86-64指令集是没有字节扩展指令的,偷了个懒不改cltq果然是不行,可以取出%rax的低四个字节,与0相比较,如果大于则说明%eax为正数,高四字节扩展为全0;如果小于说明eax为负数,扩展时需要将高四字节置1。代码如下:
154     irmovq  0xffffffff,%r8
155     mrmovq  -100(%rbp),%r9
156     andq    %r8,%r9
157     rrmovq  %r9, %rax
158 #从这里开始
159     andq    %r8,%r9
160     irmovq  $0,%r10
161     subq    %r10,%r9
162     jl      zhengshu
163     irmovq    0xffffffff00000000,%r11
164     addq    %r11,%rax
165 zhengshu:

最后调整了call printf这个小错误后,终于生成了.yo文件。
经过反复修改的最终版paixu1.ys代码如下:

  1 .pos 0
  2     irmovq stack,%rsp
  3     call main
  4     halt
  5 bubble_a:
  6     pushq   %rbp
  7     rrmovq  %rsp, %rbp
  8     rmmovq  %rdi, -40(%rbp)
  9     rmmovq  %rsi, -48(%rbp)
 10     mrmovq  -48(%rbp), %rax
 11     irmovq  $1,%r8
 12     subq    %r8, %rax
 13     rmmovq  %rax, -16(%rbp)
 14     jmp L2
 15 L6:
 16     irmovq  $0,%r9
 17     rmmovq  %r9, -24(%rbp)
 18     jmp L3
 19 L5:
 20     mrmovq  -24(%rbp), %rax
 21     irmovq  $1,%r10
 22     addq    %r10, %rax
 23     rrmovq  %rax,%r8
 24     addq    %r8,%r8
 25     addq    %r8,%r8
 26     addq    %r8,%r8
 27     rrmovq  %r8,%rdx
 28     mrmovq  -40(%rbp), %rax
 29     addq    %rdx, %rax
 30     mrmovq  (%rax), %rdx
 31     mrmovq  -24(%rbp), %rax
 32     rrmovq  %rax,%r8
 33     addq    %r8,%r8
 34     addq    %r8,%r8
35     addq    %r8,%r8
 36     rrmovq  %r8,%rcx
 37     mrmovq  -40(%rbp), %rax
 38     addq    %rcx, %rax
 39     mrmovq  (%rax), %rax
 40     rrmovq  %rax,%r9
 41     rrmovq  %rdx,%r10
 42     subq    %r9, %r10
 43     jge L4
 44     mrmovq  -24(%rbp), %rax
 45     irmovq  $1,%r8
 46     addq    %r8, %rax
 47     rrmovq  %rax,%r8
 48     addq    %r8,%r8
 49     addq    %r8,%r8
 50     addq    %r8,%r8
 51     rrmovq  %r8,%rdx
 52     mrmovq  -40(%rbp), %rax
 53     addq    %rdx, %rax
 54     mrmovq  (%rax), %rax
 55     rmmovq  %rax, -8(%rbp)
 56     mrmovq  -24(%rbp), %rax
 57     irmovq  $1,%r8
 58     addq    %r8, %rax
 59     rrmovq  %rax,%r8
 60     addq    %r8,%r8
 61     addq    %r8,%r8
 62     addq    %r8,%r8
 63     rrmovq  %r8,%rdx
 64     mrmovq  -40(%rbp), %rax
 65     addq    %rax, %rdx
 66     mrmovq  -24(%rbp), %rax
 67     rrmovq  %rax,%r8
 68     addq    %r8,%r8
69     addq    %r8,%r8
 70     addq    %r8,%r8
 71     rrmovq  %r8,%rcx
 72     mrmovq  -40(%rbp), %rax
 73     addq    %rcx, %rax
 74     mrmovq  (%rax), %rax
 75     rmmovq  %rax, (%rdx)
 76     mrmovq  -24(%rbp), %rax
 77     rrmovq  %rax,%r8
 78     addq    %r8,%r8
 79     addq    %r8,%r8
 80     addq    %r8,%r8
 81     rrmovq  %r8,%rdx
 82     mrmovq  -40(%rbp), %rax
 83     addq    %rax, %rdx
 84     mrmovq  -8(%rbp), %rax
 85     rmmovq  %rax, (%rdx)
 86 L4:
 87     irmovq  $1,%r9
 88     mrmovq  -24(%rbp),%r10
 89     addq    %r9,%r10
 90     rmmovq  %r10,-24(%rbp)
 91 L3:
 92     mrmovq  -24(%rbp), %rax
 93     mrmovq  -16(%rbp),%r8
 94     rrmovq  %rax,%r9
 95     subq    %r8,%r9
 96     jl  L5
 97     irmovq  $1,%r10
 98     mrmovq  -16(%rbp),%r11
 99     subq    %r10,%r11
100     rmmovq  %r11,-16(%rbp)
101 L2:
102     irmovq  $0,%r8
103     mrmovq  -16(%rbp),%r9
104     subq    %r8, %r9
105     jg  L6
106     nop
107     popq    %rbp
108     ret
109 LFE0:
110 LC0:
111 main:
112 LFB1:
113     pushq   %rbp
114     rrmovq  %rsp, %rbp
115     irmovq  $112,%r8
116     subq    %r8, %rsp
117 #   mrmovq  %fs:40, %rax
118 #   rmmovq  %rax, -8(%rbp)
119     xorq    %rax, %rax
120     irmovq  $2, %r8
121     rmmovq  %r8, -96(%rbp)
122     irmovq  $3, %r8
123     rmmovq  %r8, -88(%rbp)
124     irmovq  $4, %r8
125     rmmovq  %r8, -80(%rbp)
126     irmovq  $5, %r8
127     rmmovq  %r8, -72(%rbp)
128     irmovq  $6, %r8
129     rmmovq  %r8, -64(%rbp)
130     irmovq  $7, %r8
131     rmmovq  %r8, -56(%rbp)
132     irmovq  $8, %r8
133     rmmovq  %r8, -48(%rbp)
134     irmovq  $9, %r8
135     rmmovq  %r8, -40(%rbp)
136     irmovq  $0, %r8
137     rmmovq  %r8, -32(%rbp)
138     irmovq  $1, %r8
139     rmmovq  %r8, -24(%rbp)
140     rrmovq  %rbp,%r9
141     irmovq  $-96,%r10
142     subq    %r10,%r9
143     rrmovq  %r9,%rax
144     irmovq  $10,%r9
145     rrmovq  %r9,%rsi
146     rrmovq  %rax, %rdi
147     call    bubble_a
148     irmovq  0xffffffff00000000,%r8
149     mrmovq  -100(%rbp),%r9
150     andq    %r8,%r9
151     rmmovq  %r9, -100(%rbp)
152     jmp L8
153 L9:
154     irmovq  0xffffffff,%r8
155     mrmovq  -100(%rbp),%r9
156     andq    %r8,%r9
157     rrmovq  %r9, %rax
158 
159     andq    %r8,%r9
160     irmovq  $0,%r10
161     subq    %r10,%r9
162     jl      zhengshu
163     irmovq    0xffffffff00000000,%r11
164     addq    %r11,%rax
165 zhengshu:
166     rrmovq  %rax,%r8
167     addq    %r8,%r8
168     addq    %r8,%r8
169     addq    %r8,%r8
170     rrmovq  %r8,%rdx
171     irmovq  $-96,%r9
172     rrmovq  %rbp,%r10
173     addq    %r9,%r10
174     rrmovq  %r10,%rax
175     addq    %rdx, %rax
176     mrmovq  (%rax), %rax
177     rrmovq  %rax, %rsi
178     irmovq  $LC0, %rdi
179     irmovq  $0, %rax
180 #   call    printf
181     mrmovq  -100(%rbp),%r8
182     irmovq  0xffffffff,%r9
183     irmovq  $1,%r10
184     addq    %r8,%r10
185     andq    %r9,%r10
186     irmovq  0xffffffff00000000,%r11
187     andq    %r8,%r11
188     addq    %r11,%r10
189     rmmovq  %r10,-100(%rbp)
190 L8:
191     mrmovq  -100(%rbp),%r9
192     irmovq  0xffffffff,%r8
193     andq    %r8,%r9
194     irmovq  $9,%r10
195     subq    %r10,%r9
196     jle L9
197     irmovq  0xffffffff00000000,%r8
198     andq    %r8,%rax
199 #   mrmovq  -8(%rbp), %rcx
200 #   mrmovq  %fs:40,%r8
201 #   xorq    %r8, %rcx
202 #   je  L11
203 
204 L11:
205     rrmovq  %rbp,%rsp
206     popq    %rbp
207     ret
208 LFE1:
209 
210 .pos 0x600
211 stack:
  • 对于把Y86汇编翻译成机器码比较简单,如果.ys文件书写正确,那么生成的.yo文件左侧就是汇编指令对应的机器码如下图所示:

  • 如果不利用现有工具,我们完全可以利用教材P246-247两页的知识将Y86汇编翻译成机器码,翻译的方法总结如下:
  1. 通过观察指令在图4-2中确定机器码的第一个字节,如果是OPq,jXX,comvXX指令,还需要通过图4-3进一步确定第一个字节中的低4位“功能部分”;
  2. 涉及到寄存器的指令,例如rrmovq,irmovq,rmmovq等,需要根据指令中具体制定的寄存器,查图4-4中寄存器对应的数字,无寄存器用f表示;
  3. 涉及立即数、偏移地址、转移地址等数字时,要将数字的十六进制表示高位补零直至满足图4-2中的标准位数,补全后利用小端方式(低位在左、高位在右)将该数字翻译成机器中存放的数字。

4.48不使用跳转,最多使用3次条件传送

 1 #include<stdio.h>
  2 
  3 void bubble_a(long *data,long count)
  4 {
  5     long i,last,t,j;
  6     for(last = count-1;last>0;last--)
  7     {
  8         for(i = 0;i<last;i++)
  9         {
 10            t=*(data+i)-*(data+i+1); 
 11            if(t>0){
 12                 *(data+i)=t;
 13                 *(data+i)=*(data+i+1);
 14                 *(data+i+1)=t;
 15             }
 16         }
 17     }
 18 }
 19 int main()
 20 {
 21     int i;
 22     long data[10] = {2,3,4,5,6,7,8,9,0,1};
 23     bubble_a(data,10);
 24     for(i=0;i<10;i++)
 25     {
 26         printf("%d\n",*(data+i));
 27     }
 28     return 0;
 29 }

这段代码没有使用跳转指令,而是通过“
*(data+i)-*(data+i+1)”来设置条件码,通过comvg条件传送指令实现if(j>0)中的三个赋值语句。

4.49不使用跳转,最多使用1次条件传送

分析:要实现两个数的交换但是最多只使用1次条件传送指令可能需要我们借助栈来保存其中一个操作数的值。代码如下:

  1 #include<stdio.h>
  2 #include"duizhan.h"
  3 
  4 void bubble_a(long *data,long count)
  5 {
  6     long i,last,t,j;
  7     struct Stack* ps;
  8     init(ps);
  9     for(last = count-1;last>0;last--)
 10     {
 11         for(i = 0;i<last;i++)
 12         {
 13              j=*(data+i)-*(data+i+1);
 14             if(j>0)
 15             {
 16                 push(ps,*(data+i+1));
 17                 *(data+i+1)=*(data+i);
 18                 pop(ps,data+i);
 19             }
 20         }
 21     }
 22 }
 23 int main()
 24 {
 25     int i;
 26     long data[10] = {2,3,4,5,6,7,8,9,0,1};
 27     bubble_a(data,10);
 28     for(i=0;i<10;i++)
 29     {
 30         printf("%d\n",*(data+i));
 31     }
 32     return 0;
 33 }

书写这段代码之前,需要先编辑一个包含栈操作的头文件duizhan.h,其中包含栈的初始化函数init(),入栈函数push(),弹栈函数
pop()等。通过栈来保存操作数*(data+i)的值,减少了传送指令的使用次数,所以只需要根据条件码,利用一次条件传送指令给*(data+i+1)赋值即可。

任务二

多进程将daytime服务器实现为并发服务器:

多线程将daytime服务器实现为并发服务器:

码云链接_1

码云链接_2

posted on 2017-11-12 20:36  鲸鱼的抽屉  阅读(734)  评论(2编辑  收藏  举报