gpt4 book ai didi

assembly - cmp 汇编指令如何设置标志 (X86_64 GNU Linux)

转载 作者:行者123 更新时间:2023-12-04 17:16:13 27 4
gpt4 key购买 nike

这是一个简单的 C 程序:

void main()
{
unsigned char number1 = 4;
unsigned char number2 = 5;

if (number1 < number2)
{
number1 = 0;
}
}

所以在这里我们比较两个数字。在汇编中,它将使用 cmp 完成。
cmp 的工作原理是从另一个操作数中减去一个操作数。

现在 cmp 如何减去操作数?它是从第二个操作数中减去第一个操作数,反之亦然?无论如何,这应该是这样的:

情况1:

4 - 5 = (0000 0100 - 0000 0101) = (0000 0100 + 1111 1010 + 1) = (0000 0100 + 1111 1011)

= 1111 1111 = -1

因此,由于符号位 = 1,因此 SF 应为 1。

没有进位,所以 CF 应该 = 0。

案例#2:

5 - 4 = (0000 0101 - 0000 0100) = (0000 0101 + 1111 1011 + 1)

= (0000 0101 + 1111 1100) = 1 0000 0001

所以在这里,CF 应该是 = 1

由于结果为正,SF 应为 = 0

现在我编译并运行程序(linux x86_64、gcc、gdb),在 cmp 指令后放置一个断点以查看寄存器状态。

cmp后断点:
Breakpoint 2, 0x0000000000400509 in main ()
(gdb) disassemble
Dump of assembler code for function main:
0x00000000004004f6 <+0>: push %rbp
0x00000000004004f7 <+1>: mov %rsp,%rbp
0x00000000004004fa <+4>: movb $0x4,-0x2(%rbp)
0x00000000004004fe <+8>: movb $0x5,-0x1(%rbp)
0x0000000000400502 <+12>: movzbl -0x2(%rbp),%eax
0x0000000000400506 <+16>: cmp -0x1(%rbp),%al
=> 0x0000000000400509 <+19>: jae 0x40050f <main+25>
0x000000000040050b <+21>: movb $0x0,-0x2(%rbp)
0x000000000040050f <+25>: pop %rbp
0x0000000000400510 <+26>: retq
End of assembler dump.

执行 cmp 后注册转储:
(gdb) info reg
rax 0x4 4
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe608 140737488348680
rsi 0x7fffffffe5f8 140737488348664
rdi 0x1 1
rbp 0x7fffffffe510 0x7fffffffe510
rsp 0x7fffffffe510 0x7fffffffe510
r8 0x7ffff7dd4dd0 140737351863760
r9 0x7ffff7de99d0 140737351948752
r10 0x833 2099
r11 0x7ffff7a2f950 140737348041040
r12 0x400400 4195328
r13 0x7fffffffe5f0 140737488348656
r14 0x0 0
r15 0x0 0
rip 0x400509 0x400509 <main+19>
eflags 0x297 [ CF PF AF SF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)

所以我们可以看到,cmp执行后,CF=1,SF=1。

所以实际结果标志 (CF=1 & SF=1) 不等于我们计算的标志

案例#1 (CF=0 & SF=1) 或案例#2 (CF=1 & SF=0)

那到底是怎么回事? cmp 实际上是如何设置标志的?

最佳答案

CMP的操作
CMP 执行减法但不存储结果。
出于这个原因,对标志的影响在以下之间完全相同:

cmp eax,ecx
sub eax,ecx

根据 documentation :

Operation
temp ← SRC1 − SignExtend(SRC2);
ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)
Flags Affected
The CF, OF, SF, ZF, AF, and PF flags are set according to the result.



对标志的影响
因此,以下标志会受到如下影响:
Assume result = op1 - op2

CF - 1 if unsigned op2 > unsigned op1
OF - 1 if sign bit of OP1 != sign bit of result
SF - 1 if MSB (aka sign bit) of result = 1
ZF - 1 if Result = 0 (i.e. op1=op2)
AF - 1 if Carry in the low nibble of result
PF - 1 if Parity of Least significant byte is even

我建议你在这里阅读 OF 和 CF: http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt

操作数的顺序
我看到您喜欢痛苦并且正在使用称为 ATT 语法的 x86 程序集的脑残变体。
在这种情况下,您需要考虑到
CMP %EAX, %ECX  =>  result for the flags = ECX - EAX
CMP OP2, OP1 = flags = OP1 - OP2

而英特尔语法是
CMP ECX, EAX    =>  result for the flags = ECX - EAX
CMP OP1, OP2 => flags = OP1 - OP2

您可以使用以下命令指示 gdb 向您显示 Intel 语法: set disassembly-flavor intel

关于assembly - cmp 汇编指令如何设置标志 (X86_64 GNU Linux),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43841172/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com