交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
1 条件码寄存器
分享
未结
0
865
李延
LV6
2022-06-07
悬赏:20积分
# 1 控制 到目前为止我们的代码还是直线直线,也就是只能一条一条的依次按顺序执行。但在我们的c语言和其他语言中,还有许多不是安装顺序执行的情况,比如:条件语句if、循环语句等等。在汇编中,这些代码是如何实现的。 # 2 条件码 在之前介绍的16个寄存器是整数寄存器。cpu还维护了一组条件码。在执行完 之前介绍的运算逻辑后,会讲相应的属性,写进这些条件码中。比较常用的有: - CF:进位标志。最近的运算最高位产生了进位。可以检查无符号溢出情况。 - ZF:零标志。最近的运算结果为0. - SF:符号标志。最近的运算结果为负数。 - OF:溢出标志。最近的运算导致一个补码溢出。有符号的溢出。 这些条件码不可以直接编辑与访问,他们都是根据最近的一次操作结果进行设置的。一般有以下几种实用场景: - 根据某个条件码,将一个字节设置为0 或者1. - 根据某个条件码的状态,跳转到代码的位置。 # 3 访问条件码 我们可以实用set指令,将特定的计算的结果写入到某个寄存器中。一共有如下指令: | 指令 | 同义名 | 效果 | 含义 | | :----- | ------ | --------------- | ---------- | | sete | setz | ZF | 相等 | | setne | setnz | ~ZF | 不相等 | | sets | | SF | 负数 | | setns | | ~SF | 非负 | | setg | setnle | ~ (SF^OF)& ~ ZF | 大于 | | setge | setnl | ~ (SF^OF) | 大于等于 | | setl | setnge | (SF^OF) | 小于 | | setle | setng | (SF^OF) \| ZF | 小于等于 | | seta | setnbe | ~CF & ~ ZF | 超过 | | setae | setnb | ~CF | 超过或相等 | | setb | setnae | CF | 低于 | | settbe | setna | CF \| ZF | 低于或等于 | | | | | | 这里我们需要注意,set指令只可以修改最低的8位。所以使用时,我们需要手动将高位清零。 ## 3.1 sete 与setne ```asm .LC0: .string "subq value %llu\n sete value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx subq $21, %rbx movq $0,%rdx sete %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果: ```shell subq value 0 sete value 1 ``` 这里我们计算了 21-21 。将ZF 打印出来是0. 另外我们计算的如果结果不是0.如下: ```asm .LC0: .string "subq value %lld\n sete value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx subq $23, %rbx movq $0,%rdx sete %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果: ```shel subq value -2 sete value 0 ``` 注意:set后的寄存器用的都是8为的,使用其他的会报错 ```asm sete %dxl ``` setne与上面情况相反 ```asm .LC0: .string "subq value %lld\n setne value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx subq $23, %rbx movq $0,%rdx setne %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果: ```shel subq value -2 sete value 1 ``` ## 3.2 sets 与setns 这里只进行演示一个示例,其他情况与sete 相同 ```asm .LC0: .string "subq value %lld\n sets value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx subq $23, %rbx movq $0,%rdx sets %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果: ```sh subq value -2 sets value 1 ``` ## 3.3 setg 与setge 大于或等于的判断,使用的是OF寄存器,所以是对有符号的数据判断。 setg 通过表达式:~ (SF^OF)& ~ ZF 也就是说 SF = 0,OF = 0,ZF = 0 时, setg 结果才为1。那么就是说: - 上一次运算结果不为0 - 上一次运算结果不为负 - 上一次有符号运算没溢出 从上面的逻辑我们可以看到,setg 是通过判断减法运行的结果。 a-b, 如果得到的是负数,就说明 a<b,如果不为负,就是a>b。 同时也排斥有符号溢出的情况,避免溢出也得到负数,造成结果异常。 ```asm .LC0: .string "subq value %lld\n setg value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx subq $23, %rbx movq $0,%rdx setg %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果 ```shell subq value -2 setg value 0 ``` 这里我们结算的是 21-23 。 也就是比较21 和23 。21小所以setg 为0. 反之: ```asm .LC0: .string "subq value %lld\n setg value %llu\n" .globl main main: subq $56, %rsp movq $211, %rbx subq $23, %rbx movq $0,%rdx setg %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果 ```shell subq value 188 setg value 1 ``` 而 setge 与setg想比 少了~ZF 条件。也就是说结果可以为0. 所以不再写测试用例。 ## 3.4 其他 其他的结果判断都与 setg 基本一致,不再一一测试。 # 4 cmp与test 在我们之前的例子我,同时通过之前的运算符来设置这些条件码的,但他们都需要改变一个寄存器的状态。而有时,我们只需要修改条件码,不需要修改其他寄存器。这时候就需要cmp与test这两个命令 - cmp : 与sub相同,减法命令。 - test: 与AND 相同,与运算。 ## 4.1 cpm ```asm .LC0: .string "subq value %llu\n sete value %llu\n" .globl main main: subq $56, %rsp movq $21, %rbx cmpq $21, %rbx movq $0,%rdx sete %dxl movl $.LC0, %edi movq %rbx, %rsi call printf movl $0, %eax addq $56, %rsp ret ``` 结果 ```shell subq value 21 sete value 1 ``` 这里我们计算21-21. sete结果是1 。与我们上面一致。 但不同的是我们使用sub时,寄存器 rbx 保存的是计算结果0. 而cpm 还是原来的值21 ## 4.2 test test 是And 计算。常被用做判断一个数是否为负。比如: ```asm .LC0: .string "testq value %llu\n" .globl main main: subq $56, %rsp movq $-21, %rbx testq %rbx,%rbx movq $0,%rsi sets %sil movl $.LC0, %edi call printf movl $0, %eax addq $56, %rsp ret ``` 结果: ```shell testq value 1 ```
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号