переносить / переполнять и вычитать в x86 - PullRequest
11 голосов
/ 23 января 2012

Я пытаюсь обернуть голову вокруг переполнения и перенести флаги в x86.

Насколько я понимаю, для добавления номеров дополнений со знаком 2 флаги могут быть сгенерированы только одним из четырех способов (мои примеры - 4-битные числа):

  1. pos + pos = neg (переполнение)
    • 0111 + 0001 = 1000 (7 + 1 = -8)
  2. pos + neg = pos (нести)
    • 0011 + 1110 = 0001 (3 + -2 = 1)
  3. Нег + Нег = Нег (нести)
    • 1111 + 1111 = 1110 (-1 + -1 = -2)
  4. neg + neg = pos (переполнение и перенос)
    • 1000 + 1001 = 0001 (-8 + -7 = 1)

Итак, в сборке x86 вычитание B из A генерирует те же флаги, что и добавление A и -B?

Ответы [ 2 ]

18 голосов
/ 24 января 2012

Вот справочная таблица, которая может помочь. Это показывает пример каждой возможной комбинации 4 арифметических флагов, которые могут быть результатом инструкций ADD и SUB на x86. «h», «ud» и «d» означают шестнадцатеричное, беззнаковое десятичное и знаковое десятичное представления каждого значения. Например, первая строка для SUB говорит 0xFF - 0xFE = 0x1 без установленных флагов.

Но я думаю, что короткая история в том, что Алекс правильно ответил.

 ADD
       A                   B                   A + B              Flags  
 ---------------     ----------------    ---------------      -----------------
 h  |  ud  |   d   | h  |  ud  |   d   | h  |  ud  |   d   | OF | SF | ZF | CF
 ---+------+-------+----+------+-------+----+------+-------+----+----+----+---
 7F | 127  |  127  | 0  |  0   |   0   | 7F | 127  |  127  | 0  | 0  | 0  | 0
 FF | 255  |  -1   | 7F | 127  |  127  | 7E | 126  |  126  | 0  | 0  | 0  | 1
 0  |  0   |   0   | 0  |  0   |   0   | 0  |  0   |   0   | 0  | 0  | 1  | 0
 FF | 255  |  -1   | 1  |  1   |   1   | 0  |  0   |   0   | 0  | 0  | 1  | 1
 FF | 255  |  -1   | 0  |  0   |   0   | FF | 255  |  -1   | 0  | 1  | 0  | 0
 FF | 255  |  -1   | FF | 255  |  -1   | FE | 254  |  -2   | 0  | 1  | 0  | 1
 FF | 255  |  -1   | 80 | 128  | -128  | 7F | 127  |  127  | 1  | 0  | 0  | 1
 80 | 128  | -128  | 80 | 128  | -128  | 0  |  0   |   0   | 1  | 0  | 1  | 1
 7F | 127  |  127  | 7F | 127  |  127  | FE | 254  |  -2   | 1  | 1  | 0  | 0


 SUB
       A                   B                   A - B              Flags  
 ---------------     ----------------    ---------------      -----------------
 h  |  ud  |   d   | h  |  ud  |   d   | h  |  ud  |   d   || OF | SF | ZF | CF
----+------+-------+----+------+-------+----+------+-------++----+----+----+----
 FF | 255  |  -1   | FE | 254  |  -2   | 1  |  1   |   1   || 0  | 0  | 0  | 0
 7E | 126  |  126  | FF | 255  |  -1   | 7F | 127  |  127  || 0  | 0  | 0  | 1
 FF | 255  |  -1   | FF | 255  |  -1   | 0  |  0   |   0   || 0  | 0  | 1  | 0
 FF | 255  |  -1   | 7F | 127  |  127  | 80 | 128  | -128  || 0  | 1  | 0  | 0
 FE | 254  |  -2   | FF | 255  |  -1   | FF | 255  |  -1   || 0  | 1  | 0  | 1
 FE | 254  |  -2   | 7F | 127  |  127  | 7F | 127  |  127  || 1  | 0  | 0  | 0
 7F | 127  |  127  | FF | 255  |  -1   | 80 | 128  | -128  || 1  | 1  | 0  | 1
8 голосов
/ 23 января 2012

Все 4 комбинации значений переноса и переполнения возможны при сложении или вычитании.Вы можете увидеть больше примеров в этом ответе .

Этот ответ содержит доказательство того факта, что перенос, который вы получаете от A-B, является инверсиейнести вы получите от A+(-B).Код по первой ссылке использует это свойство для преобразования ADC в SBB.

Однако значение флага переполнения со знаком должно быть одинаковым как для A-B, так и для A+(-B), поскольку оно зависит отнезависимо от того, имеет ли результат правильный знаковый бит, и в обоих случаях бит знака будет одинаковым.

...