簡體   English   中英

cmp匯編指令如何設置標志(X86_64 GNU Linux)

[英]How cmp assembly instruction sets flags (X86_64 GNU Linux)

這是一個簡單的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

根據文件

手術
temp←SRC1 - SignExtend(SRC2);
ModifyStatusFlags; (*以與SUB指令相同的方式修改狀態標志*)
受影響的旗幟
根據結果​​設置CF,OF,SF,ZF,AF和PF標志。

對旗幟的影響
所以以下標志會受到影響:

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-syntax的x86程序集的braindead變體。
在這種情況下,您需要考慮到這一點

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

我想我現在明白了。 這就是我認為的方式(借旗設置)

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。

所以我們看到第一個操作數的第2位是1。

當位2 = 1時,表示4。

我們知道我們可以把4寫成2 + 2.所以我們可以寫4作為兩個2。

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

所以在上面的步驟中,我們將第一個操作數的第4位寫為兩個2(第一個操作數的第2位頂部的兩個1)。

現在我們再次知道,2可以寫成兩個1。 所以我們從第一個操作數的第1位借一個1,在第一個操作數的第0位寫兩個1。

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

現在我們准備在第0位和第1位執行減法。

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

因此在解決了位0和位1后,讓我們看看第2位。

我們再次看到同樣的問題。

第1個操作數的第2位= 0

第2個操作數的第2位= 1

為此,讓我們從第一個操作數的第2位左側借一個1。

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

現在你看,第一個操作數的第8位是1.我們借了這個1。

在此階段,將設置進位標志。 所以CF = 1。

現在,如果第8位為1,則表示256。

256 = 128 + 128

如果第7位為1,則表示128.我們可以重寫為

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

如前所述,我們可以將其重寫為:

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

如前所述,我們可以將其重寫為:

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

如前所述,我們可以將其重寫為:

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

如前所述,我們可以將其重寫為:

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

如前所述,我們可以將其重寫為:

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

最后我們可以解決這個問題。

從上面的所有中減去第二個操作數將給出

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


So result = 1111 1111

注意,結果中的符號位=位7 = 1

所以將設置標志標志。 即SF = 1

因此SF = 1,在4-5之后CF = 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM