我想移动比较结果设置的零标志,例如“cmp rax,rbx”,进入寄存器。我知道我可以使用 PUSHF/PUSHFD/PUSHFQ 之一将标志推入堆栈,但现在我只想将零标志从堆栈移动到寄存器。
根据 https://www.felixcloutier.com/x86/pushf:pushfd:pushfq,它“将堆栈指针减 4(如果当前操作数大小属性为 32)并推送 EFLAGS 的全部内容注册到堆栈上。”但这并没有告诉我它们被推送的顺序以及如何访问零标志。
根据英特尔软件开发人员手册(2023 年 6 月)第 7.3.13.2 节,零标志是从零开始的 #6。因此,我猜测“mov al,[rsp+6]”可以做到这一点。但我需要确定,因为它们都只是布尔值——我可能会获取错误的布尔值。
我处于 64 位模式,因此我将寻址 RFLAGS 寄存器。手册第 7.3.1.4 节说:“PUSHF 和 POPF 在 64 位模式下的行为与非 64 位模式下的行为相同。PUSHFD 始终将 64 位 RFLAGS 压入堆栈(RF 和 VM 标志读为清除) ). POPFD 始终从堆栈顶部弹出 64 位值,并将低 32 位加载到 RFLAGS。然后将 RFLAGS 的高位进行零扩展。”
最后,PUSHFD 和 PUSHFQ 有什么区别?双字和四字,但在 64 位模式下我应该使用哪个?
感谢您对此的任何帮助。
此 MASM 示例从 RFLAGS 寄存器中提取 ZF(位 #6) 并将其存储在
rcx
寄存器中。
option casemap:none
.code
main proc
mov rax,0 ; Init to 0
mov rbx,0 ; Init to 0
cmp rax,rbx ; Comparison equal, sets ZF=1
pushfq ; Push RFLAGS onto the stack
pop rcx ; Load the RFLAGS from the stack into rcx
shr rcx, 6 ; Shift right by 6, so the ZF is now the LSB of rcx
and rcx, 1 ; Zero all other bits, except the LSB
; rcx contains the ZF moved from the stack to a register
ret
main endp
end
根据对 Intel RFLAGS 和 POPFQ PUSHFQ 的评论?
64位模式已经使用PUSHFQ。引用手册:“在 64 位模式下, 该指令的默认操作是递减堆栈指针 (RSP) 乘 8 并将 RFLAGS 压入堆栈。”