selph
selph
发布于 2022-01-04 / 380 阅读
0
0

《xchg rax,rax》片段分析0x03--取二者最小值

前言

本次是该系列的的第0x03篇


实验环境:

  • Windows10 + VS2022 + masm

0x03

代码片段链接:xorpd | xchg rax,rax 0x03

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

代码分析

这里的指令都是很基础的常见指令,就不做介绍了

代码片段分析

给定不同的值给寄存器来观察运行结果,若第一个sub结果为正:

.code
main proc
;rax = 10
;rdx = 15
    lea rax, [10]
    lea rdx, [15]

    sub      rdx,rax    ;rdx = 5, CF=0
    sbb      rcx,rcx    ;rcx = 0
    and      rcx,rdx    ;rcx = 0
    add      rax,rcx    ;rax = rax = 10

	ret

main ENDP
END

若第一个sub结果为负:

.code
main proc
;rax = 10
;rdx = 5
    lea rax, [10]
    lea rdx, [5]

    sub      rdx,rax    ;rdx = -5, CF=1
    sbb      rcx,rcx    ;rcx = -1
    and      rcx,rdx    ;rcx = rdx = -5
    add      rax,rcx    ;rax = rax + rcx = 5

	ret

main ENDP
END

总结如下:短短4行,实现了取二者最小值的功能,这里通过sbb指令判断需要比较的两个寄存器的大小情况,根据sbb指令的结果来判断是否需要让一个操作数变成原来的另一个操作数,能够省略条件判断和跳转,感觉很厉害

.code
main proc
;rax = 10
;rdx = 5
    lea rax, [10]
    lea rdx, [5]

    sub      rdx,rax    ;通过CF位来标记两个操作数的大小情况
    sbb      rcx,rcx    ;根据CF位来为两种情况准备辅助操作数
    and      rcx,rdx    ;如果rdx大,则rcx为0,rdx小,则rcx为rdx
    add      rax,rcx    ;rax = rax + rcx,如果rdx大,则rax不变,如果rdx小,则rax = rax + 计算后的rdx = rax + rdx - rax = 原来的rdx

	ret

main ENDP
END

评论