cmp汇编指令如何设置标志(X86_64 GNU Linux)
这是一个简单的C程序:
void main() { unsigned char number1 = 4; unsigned char number2 = 5; if (number1 < number2) { number1 = 0; } } 所以我们在这里比较两个数字.在汇编中,它将使用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:
对旗帜的影响 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 操作数的顺序 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语法: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |