cmp汇编指令如何设置标志(X86_64 GNU Linux) [英] How cmp assembly instruction sets flags (X86_64 GNU Linux)

查看:120
本文介绍了cmp汇编指令如何设置标志(X86_64 GNU Linux)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个简单的C程序:

Here is a simple C program:

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

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

所以在这里,我们正在比较两个数字.组装时将使用cmp完成. cmp的工作原理是从另一个操作数减去一个操作数.

So here we are comparing two numbers. In assembly it will be done using cmp. cmp works by subtracting one operand from other.

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

Now how cmp is subtracting operands? Is it subtracting 1st operand from 2nd or vice versa? In any case, this should go like this:

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

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

= 1111 1111 = -1

= 1111 1111 = -1

因此,由于符号位= 1,所以SF应该为1.

So since the sign bit = 1 so SF should be 1.

没有进位,因此CF应该= 0.

No carry, so CF should be = 0.

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

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

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

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

所以在这里,CF应该= 1

so here, CF should be = 1

由于结果为正,因此SF应该为0

since result is positive, SF should be = 0

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

Now I compile and run program (linux x86_64, gcc, gdb), place a breakpoint after cmp instruction to see register states.

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.

So we can see that after cmp has been executed, both CF=1, SF=1.

因此,实际结果标志(CF = 1和SF = 1)不等于我们在

So the actual resulted flags (CF=1 & SF=1) are not equal to flags we calculated in

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

Case # 1 (CF=0 & SF=1) or case # 2 (CF=1 & SF=0)

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

Whats happening then? How cmp is actually setting the flags?

推荐答案

我想我现在明白了.这就是我的想法(设置了借款标志)

I think i understand it now. This is how i think it goes (borrow flag is set)

4 - 5

1st operand = 4 = 0000 0100
2nd operand = 5 = 0000 0101

So we have to perform

      1st operand
    - 2nd operand
    --------------


      7654 3210 <-- Bit number
      0000 0100
    - 0000 0101
    ------------

Lets start.

Bit 0 of 1st operand = 0
Bit 0 of 2nd operand = 1

so

  0
- 1 
 ===
  ?

为此,

让我们从第一个操作数的第0位的左侧借一个1.

let's borrow a 1 from left side of bit 0 of 1st operand.

所以我们看到第一个操作数的位2是1.

so we see bit 2 of 1st operand is 1.

当位2为= 1时,表示4.

when bit 2 is = 1, it means 4.

我们知道我们可以将4写成2 +2.所以我们可以将4写成两个2.

we know that we can write 4 as 2 + 2. So we can write 4 as two 2s.

      7654 3210 <-- Bit number
             1
             1         
      0000 0000
    - 0000 0101
    ------------

因此,在上面的步骤中,我们将第一个操作数的第4位写为两个2(在第一个操作数的第2位的顶部有两个1).

So in above step, we have written bit 4 of 1st operand as two 2s (two 1 on top of bit 2 of 1st operand.)

再一次,我们知道,一个2可以写成两个1. 因此,我们从第一个操作数的位1借一个1,并在第一个操作数的位0上写两个1.

Now again as we know, a 2 can be written as two 1s. So we borrow one 1 from bit 1 of 1st operand and write two 1s on bit 0 of 1st operand.

      7654 3210 <-- Bit number
              1
             11         
      0000 0000
    - 0000 0101
    ------------

现在我们准备对位0和位1进行减法.

Now we are ready to perform subtraction on bit 0 and bit 1.

      7654 3210 <-- Bit number
              1
             11         
      0000 0000
    - 0000 0101
    ------------
             11

因此,在解决了位0和位1之后,让我们看一下位2.

So after solving bit 0 and bit 1, lets see bit 2.

我们再次遇到相同的问题.

We again see same problem.

第一个操作数的位2 = 0

Bit 2 of 1st operand = 0

第二个操作数的位2 = 1

Bit 2 of 2nd operand = 1

要做到这一点,让我们从第一个操作数的第2位的左侧借一个1.

to do this, let's borrow a 1 from left side of bit 2 of 1st operand.

    8 7654 3210 <-- Bit number
              1
             11         
    1 0000 0000
    - 0000 0101
    ------------
             11

现在您看到,第一个操作数的第8位是1.我们已经借用了这个1.

Now you see, bit 8 of 1st operand is 1. We have borrowed this 1.

在此阶段,将设置进位标志.因此CF = 1.

At this stage, carry flag will be set. So CF=1.

现在,如果位8为1,则表示256.

Now, if bit 8 is 1, it means 256.

256 = 128 + 128

256 = 128 + 128

如果第7位为1,则表示128.我们可以重写为

if bit 7 is 1, it means 128. We can rewrite as

    8 7654 3210 <-- Bit number
      1       1
      1      11         
      0000 0000
    - 0000 0101
    ------------
             11

像以前一样,我们可以将其重写为:

As previously, we can re-write it as:

    8 7654 3210 <-- Bit number
       1      1
      11     11         
      0000 0000
    - 0000 0101
    ------------
             11

和以前一样,我们可以将其重写为:

As previously, we can re-write it as:

    8 7654 3210 <-- Bit number
        1     1
      111    11         
      0000 0000
    - 0000 0101
    ------------
             11

和以前一样,我们可以将其重写为:

As previously, we can re-write it as:

    8 7654 3210 <-- Bit number
         1    1
      1111   11         
      0000 0000
    - 0000 0101
    ------------
             11

像以前一样,我们可以将其重写为:

As previously, we can re-write it as:

    8 7654 3210 <-- Bit number
           1  1
      1111 1 11         
      0000 0000
    - 0000 0101
    ------------
             11

像以前一样,我们可以将其重写为:

As previously, we can re-write it as:

    8 7654 3210 <-- Bit number
            1 1
      1111 1111         
      0000 0000
    - 0000 0101
    ------------
             11

最后我们可以解决这个问题.

At last we can solve this.

从上面减去第二个操作数将得到

Subtracting 2nd operand from all above it will give

    8 7654 3210 <-- Bit number
            1 1
      1111 1111         
      0000 0000
    - 0000 0101
    ------------
      1111 1111


So result = 1111 1111

请注意,对结果中的位进行签名=位7 = 1

Notice, sign bit in result = bit 7 = 1

因此将设置标志标志.即SF = 1

so sign flag will be set. i.e SF=1

因此SF = 1,CF = 1,CF = 4-5

And therefore SF=1, CF=1 after 4 - 5

这篇关于cmp汇编指令如何设置标志(X86_64 GNU Linux)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆