【问题标题】:Use of carry flag for SBB RCX,RCX after subtractionSBB RCX,RCX 减法后进位标志的使用
【发布时间】:2015-09-24 22:27:31
【问题描述】:

我正在看书:[xchg rax, rax]。以下是本书的 0x03 sn-p,我无法理解这一点。

sub      rdx,rax
sbb      rcx,rcx
and      rcx,rdx
add      rax,rcx

我从一个星期以来一直在研究这个(每天几分钟)。我研究了一些试图解决它的事情:数字的符号表示、减法的工作原理、减法后 CF 的作用。根据this 的回答和here 给出的列表。我看不出减法后检查 CF 的意义,除非可能溢出。

在什么情况下检查减法后的进位标志有用?

【问题讨论】:

标签: assembly x86-64


【解决方案1】:

实际上,该代码是一种巧妙的无分支方式来处理rax = min(rax, rdx)

sub rdx, rax ; rdx = rdx - rax; CF set if rdx < rax
sbb rcx, rcx ; rcx = all 1 bits if CF was set, 0 otherwise
and rcx, rdx ; rcx = rdx - rax if CF was set, 0 otherwise
add rax, rcx ; rax = rax + (rdx - rax) = rdx if CF was set, unchanged otherwise

一个更易读的分支版本是:

cmp rdx, rax
jnc done ; if rdx - rax produced no carry, rax is smaller or equal
mov rax, rdx ; otherwise rdx is the smaller one
done:

它仍然只是使用 CF 进行溢出检查。

【讨论】:

  • sub/sbb/and/add 版本比 cmp/cmov 没有优势,是吗?在 rdx 和 rax 都准备好之前,该序列无法执行,与 cmov 相同,但它需要更多的微指令。 adcsbb 都与 cmov 一样昂贵(英特尔为 2 uop,因此在不从 uop 缓存运行时存在相同的复杂解码瓶颈)。只有 AMD CPU 将 sbb 识别为仅取决于标志,但这并不重要,因为 rdx 和标志都是由同一条指令产生的。所以无论如何,这应该与 cmp/cmov 执行相同的操作,加上关键路径上的 2 条其他指令
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2020-05-25
  • 2014-02-24
  • 2016-01-15
相关资源
最近更新 更多