博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第8周课下作业1(补)
阅读量:7223 次
发布时间:2019-06-29

本文共 2179 字,大约阅读时间需要 7 分钟。

第8周课下作业1(补)

(蓝墨云上未提交,课下补的)

1 完成家庭作业4.47,4.48,4.49

2 相应代码反汇编成X86-64汇编
3 把上述X86-64汇编翻译成Y86汇编,并给出相应机器码

4.47

用指针引用数组元素实现冒泡排序:

void bubble_a(long *data,long count)  {       long i,last,t;       for(last = count-1;last>0;last--)       {           for(i = 0;i

测试结果:

image

这个函数和测试代码组成的Y86-64程序:

首先通过分步编译,得到对应的X86汇编程序,再将x86(Bubble_sort.s) 手动翻译为Y86(Bubble_sort.ys)(),注意y86与x86的不同之处(见书上P252):

  1. Y86中要将常数加载到寄存器再进行计算,它在算术指令中不能使用立即数。
  2. 要实现从内存读取一个数值并将其与一个寄存器相加,Y86需要两条指令,先将内存中的数装到寄存器里。
  3. Y86的整数操作指令会设置条件码,不需要testq指令,直接使用跳转指令。
  4. 由于Y86-64指令集中所以操作都以8个字节为单位,所以在转换“movl,addl”这些四字节指令时要注意进行符号拓展。

4.48

修改4.47的代码要求不使用跳转,最多使用三次条件传送。

我重新复习并详读了P145——用条件传送实现条件分支。

  • 条件传送的核心是:计算一个条件操作的两种结果,然后再根据条件是否满足从中选取一个。
  • X86-64上可用的条件传送指令具体见P147图3-18
  • 处理器执行条件传送指令:读源值(内存或寄存器),检查条件码,然后要么更新目的寄存器,要么保持不变。

对于这道题,要实现6~11行冒泡排序的测试与交换,且求不使用跳转,最多使用三次条件传送。

  1. 首先必须要看懂X86汇编代码,找到测试与交换这段C程序对应的x86汇编代码,通过我对汇编代码一行行的努力仔细分析,最终找到了对应汇编代码:
leaq    8(%rdi,%rax,8), %rsi    movq    (%rsi), %rcx          #从内存装入dada[i]到%rcx    leaq    (%rdi,%rax,8), %rdx    movq    (%rdx), %r8           #从内存装入dada[i+1]到%r8    cmpq    %r8, %rcx    jge .L3                       #如果%r8>=%rcx,即dada[i+1]>=dada[i],跳转到.L3改变i值进入下一次循环。    movq    %r8, (%rsi)               movq    %rcx, (%rdx)        #这里是两数交换的汇编代码,只需将寄存器里的值交叉传回内存,不需要借助第三方。

显然这里用了一次跳转,根据条件传送指令使用规则,可以这样改写:

  • 不管前面怎么写,最终是一定要从寄存器传回内存。
  • 考虑用条件传送cmovnge(有符号<),当%r8<%rcx,即dada[i+1]<dada[i]时,从内存交叉传到寄存器。
  • 再从寄存器对应传回内存。
  • 这样使用了两次条件传送。
leaq    8(%rdi,%rax,8), %rsi    movq    (%rsi), %rcx              leaq    (%rdi,%rax,8), %rdx    movq    (%rdx), %r8        cmpq    %r8, %rcx    cmovnge (%rsi),%r8    cmpq    %r8, %rcx    cmovnge (%rdx),%rcx        movq    %r8, (%rdx)               movq    %rcx, (%rsi)

4.49

修改4.47的代码要求不使用跳转,最多使用一次条件传送。

这里的分析与4.48同理。需要考虑的是如何将上一题中两次条件传送合并为一次条件传送

我注意到两次条件传送的条件都是同一个,可以这样考虑,虽然这是在汇编程序里,实现两数交换的方式是,是在寄存器和内存之间交叉传送

但我们不妨考虑在高级语言里实现两数交换的方式,即借助第三个变量%r9,这样只需在最后一步交换时,判断是否传送,即仅一次条件传送。

leaq    8(%rdi,%rax,8), %rsi    movq    (%rsi), %rcx              leaq    (%rdi,%rax,8), %rdx    movq    (%rdx), %r8        movq    %rcx, %r9    movq    %r8, %rcx        cmpq    %r8, %r9    cmovnge %r9,%r8        movq    %r8, (%rdx)               movq    %9, (%rsi)

转载于:https://www.cnblogs.com/clever-universe/p/8004522.html

你可能感兴趣的文章
windows server 2008 域控安装
查看>>
编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议6~10)...
查看>>
Oracle查看和修改连接数(进程/会话/并发等等)
查看>>
【SpringMVC学习06】SpringMVC中的数据校验
查看>>
Laravel错误与日志处理
查看>>
微信小程序开发教程第七章:微信小程序编辑名片页面开发
查看>>
Java并发编程:Java ConcurrentModificationException异常原因和解决方法
查看>>
浅谈iOS中MVVM的架构设计
查看>>
node.js 中模块的循环调用问题详解
查看>>
ActiveReports 报表应用教程 (6)---分组报表
查看>>
OLEDB操作Excel
查看>>
struts2的json-default和struts-default的区别
查看>>
java中<> 的用法
查看>>
IIS 下配置无后缀的URL ReWrite
查看>>
对Asp.net Mvc 和 jQuery UI使用者的一些忠告
查看>>
Silverlight开发历程—动画(实现跑马灯效果)
查看>>
怎么说???
查看>>
[原]Windows批处理命令学习一
查看>>
AaronYang风格 C语言挑讲[一][基本入门]
查看>>
【oneday_onepage】——The Secret Of Steve<1>
查看>>