cmu15213 L6 Machine-Level Programming II: Control

在这里插入图片描述

Control

在这里插入图片描述
%rsp 中存放的是现在的指针栈顶(有元素入栈的时候,栈顶指针是减小的,也就是说栈是从高地址向低地址延申的)

%rip (instruction pointer)里面放的是当前指令的地址(pc program counter)

旧的有 8 个寄存器,新加的 8 个寄存器是 %r8-%r15
在这里插入图片描述
CF 无符号数的进位符(carry)(最高位进位,也就是无符号数产生了溢出)

SF 有符号数的 sign flag,1 表示负数

ZF zero flag

OF 有符号数的溢出标志位(overflow flag)(两个正数相加小于零 或 两个负数相加大于等于零)

总结:相当于是有符号数溢出看 OF,无符号数溢出看 CF
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
cmpq b,a 是计算 a-b 哦,后减前哦。
在这里插入图片描述
testq b,a 则是计算 a&b
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实际操作:
在这里插入图片描述
在这里插入图片描述

Conditional branches

在这里插入图片描述
在这里插入图片描述
cmpq %rsi, %rdi 是后减前 (%rdi-%rsi

movq %rdi, %rax 是前移后(%rdi 移到 %rax

subq %rsi, %rax 是后减前 (%rax - %rsi

总结:移动的时候是前移后,算数运算时是后 op 前
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Loops

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里的初始判断可以省略,根据视频我感觉他说的意思是:编译器在优化的时候会先判断一下初始的 i 是否满足 test 的这个条件,假如满足的话,那就直接扔掉这个 initial test

Switch Statements

在这里插入图片描述
教授说这种设计很糟糕hhhhh

在这里插入图片描述
switch 的汇编代码和 多个 if-else 并不一样。

在这里插入图片描述
这里是 ja jump above ,此处用了一个小技巧,ja 是无符号数比较,所以一个负数当作无符号数时会被认为是一个非常大的值,所以这句话的效果是,当 x>6 或者 x 为负数时就跳到 default 处。此处不用 jg (jump greater than),因为 jg 是有符号数的比较跳转。真的🐂🍺

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里计算好之后直接在 break 处 return ,return 的值存在 %rax

在这里插入图片描述
这里很奇特,因为在 case 1,2 的时候是没有用到 w 的初值的(是直接给 w 进行了赋值),所以编译器在整个 switch 之前压根就没进行 w 的初始化(🐂🍺),而在 case 3 处,我突然需要初值了,那就赶紧在前面加了一句…

在这里插入图片描述
movl 移的是 32 bits ,可以将 %rax 的高位置零(%rax 是 64 bit,%eax 是 32 bit)
在这里插入图片描述
底下有个学生问了个问题:假如 case 只有 1 和 1000000,那中间的都要建表吗?教授说,编译器会聪明地把这个转化成 if-else 。

另一个问题是,假如某些 case 本身就是负值,该怎么办?回答是:会加上一个偏置使他们变成非负的(第一个 case 变成 0)。

真的🐂🍺

总之 switch 语句可以使查找变成 O(n)O(n) ,假如是稀疏大值,编译器会建立一个 if-else 树,使得跳转树到每个 case 都是 O(logn)O(\log{n}) 的。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

posted @ 2020-05-08 10:52  winechord  阅读(114)  评论(0编辑  收藏  举报