系列文章目录
程序的机器级表示:
CSAPP第三章的目录
- 历史观点
- 程序编码
- 数据格式
- 访问信息
- 算数和逻辑操作
- 控制
- 过程
- 数组分配和访问
- 异质的数据结构
- 在机器级程序中奖控制与数据结合起来
- 浮点代码
九曲阑干的课程目录:
- 机器级代码(至书的3.4.1)
- 数据传送指令(至书的3.5.4)
- 条件码寄存器 (至书3.6.2)
- 跳转指令
- 过程
- 多维数组与结构体
- 缓冲区溢出
文章目录
前言
流程就是得到了结果去写条件码寄存器里面的内容,每得到一个结果就去写条件码寄存器,结果是可以覆盖的(相当于重写)。所以ALU不仅会更新目的寄存器(大部分操作),还会更新条件码寄存器。
参考
这里将参考列出来:
一、条件码寄存器(Condition Code Register)
条件码寄存器就是一个划分了很多个小区域的存储空间,里面每一位所代表的含义都是固定的。
我这里仅介绍这四位
下面操作不仅改变目的寄存器,也会改变条件码寄存器:
下面操作就很特别,它们与某些操作运行机制一样,但只改变条件寄存器,不改变目的操作数:
二、访问条件码
示例
sete
中的e是equal的意思。
上面的例子是等于的情况,下面来说说小于的情况:
大于小于的判断(分为有无符号数)
有符号数用OF:
无符号数用CF:
总结
条件码:
条件码寄存器都是单个位的,是不同于整数寄存器的另一组寄存器。
条件码描述了最近的算术或逻辑操作的属性,可以通过检测这些寄存器来执行条件分支指令。
常用条件码:
- CF:进位标志。最近的操作使最高位产生了进位。可以用来检查无符号数的溢出
- ZF:零标志。最近的操作的结果为 0
- SF:符号标志。最近的操作的结果为负数。
- OF:溢出标志。最近的操作导致了补码溢出
除了 leaq 指令外,其余的所有算术和逻辑指令都会根据运算结果设置条件码。
此外还有两类特殊的指令,他们只设置条件码不更新目的寄存器:
- cmp s1, s2: 除了不更新目的寄存器外与 sub 指令的行为相同
- test s1, s2: 除了不更新目的寄存器外与 and 指令的行为相同
访问条件码:
条件码一般不直接读取,常用的使用方法有 3 种:
- 根据条件码的某种组合,使用 set 指令类将一个字节设置为 0 或 1。
- 条件跳转到程序的某个其他部分
- 有条件地传送数据
set 指令类
set 指令的目的操作数是低位单字节寄存器元素或一个字节的内存位置。set 会将该字节设置为 0 或 1
set 指令类的后缀指明了所考虑的条件码的组合,如 setl (set less) 表示“小于时设置”
Appendix
SF ^ OF
是一个逻辑表达式,其中 ^
表示异或(XOR)操作。在计算机编程和微处理器的指令集中,SF
表示符号标志(Sign Flag),而 OF
表示溢出标志(Overflow Flag)。这两个标志通常在执行算术操作后由处理器设置,以反映操作的结果。
异或操作 (^
)
异或操作是一种二进制操作,它对两个位值进行比较。如果两个比较的位不同,则结果为1;如果相同,则结果为0。具体来说:
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
1 ^ 1 = 0
SF ^ OF
的用途和意义
在算术操作(尤其是加法和减法)中,SF ^ OF
的结果用于检测结果是否正确地表示了预期的数学值,特别是在涉及有符号数时。这个表达式的结果主要用于以下方面:
-
检测有符号数的算术运算是否导致异常结果。 如果一个操作导致结果的符号不正确(例如,两个正数相加得到一个负数),这通常意味着发生了溢出。
SF ^ OF
正是用来检测这种情况。 -
在条件分支中作为决策依据。 在编写低级或性能敏感的代码时,程序员可能会根据
SF ^ OF
的结果来决定执行某些操作,比如错误处理或特殊情况的处理。如果SF ^ OF
为1,这表示结果的符号与预期不符,可能需要特别处理。
示例
考虑一下几种情况,看看 SF ^ OF
如何反映结果的性质:
-
正常情况:
- 加法:
5 + 3 = 8
(无溢出)SF = 0
,OF = 0
, 因此SF ^ OF = 0
- 减法:
5 - 3 = 2
(无溢出)SF = 0
,OF = 0
, 因此SF ^ OF = 0
- 加法:
-
异常情况:
- 加法:
127 + 1 = 128
在8位有符号整数中转变为-128
(溢出)SF = 1
,OF = 1
, 因此SF ^ OF = 0
(虽然结果为负,但溢出解释了为何符号位是1)
- 加法:
-128 + (-1) = -129
在8位有符号整数中转变为127
(溢出)SF = 0
,OF = 1
, 因此SF ^ OF = 1
(结果为正,但预期为负)
- 加法:
在这些例子中,SF ^ OF
有助于揭示结果是否因为算术溢出而与预期的符号不符。这是处理器设计和编程中重要的一部分,尤其是在处理异常和错误的情况下。