Skip to content

Invalid AF calculation - scasb, scasd, add, adc, sbb, sub, cmp, inc, dec #20

Description

@mfaerevaag

Description

The AF flag is being calculated in much the same way as the OF flag, but this is not the correct behaviour. Instead of taking the carry of a whole byte, it should take the 5th bit (zero indexed), as a decimal number is represented by five bits in BCD.

Reference:
scasb, scasd: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2B 4-590
adc: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2A 3-26
add: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2A 3-31
sbb: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2B 4-587
sub: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2B 4-652
cmp: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2A 3-153
inc: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2A 3-451
dec: Ref. Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 2A 3-285

Affected instructions:

0xae         # scasb
0xaf         # scasd
0x0000       # add
0x0100
0x0200
0x0300
0x0442
0x0542424242
0x1000       # adc
0x1100
0x1200
0x1300
0x1400
0x1500000000
0x18c0       # sbb
0x19c0
0x1ac0
0x1bc0
0x1c00
0x1d00000000
0x2800       # sub
0x2900
0x2a08
0x2b08
0x2c42
0x3800       # cmp
0x3900
0x3a00
0x3b00
0x3c42
0x3d42424242
0x40         # inc
0x41
0x42
0x43
0x44
0x45
0x46
0x47
0xfe00
0xff00
0x48         # dec
0x49
0x4a
0x4b
0x4c
0x4d
0x4e
0x4f

NOTE: All combinations of prefixes are omitted.

Reproduction guide

Instruction:

00000000  0000              add [eax],al

Input:

binsec disasm -decode 0000

Observed output:

              ⎧ 0: res8 := (@[eax₍₃₂₎]₁ + eax₍₃₂₎{0,7})
              ⎪ 1: OF := ((@[eax₍₃₂₎]₁{7} = eax₍₃₂₎{0,7}{7}) && (@[eax₍₃₂₎]₁{7} ≠ res8₍₈₎{7}))
              ⎪ 2: SF := (res8₍₈₎ <𝒔 0₍₈₎)
              ⎪ 3: ZF := (res8₍₈₎ = 0₍₈₎)
add [eax], al ⎨ 4: AF := ((extu @[eax₍₃₂₎]₁{0,7} 9) + (extu eax₍₃₂₎{0,7}{0,7} 9)){8}
              ⎪ 5: PF := ¬(((((((res8₍₈₎{0} ⨁ res8₍₈₎{1}) ⨁ res8₍₈₎{2}) ⨁ res8₍₈₎{3}) ⨁ res8₍₈₎{4}) ⨁ res8₍₈₎{5}) ⨁ res8₍₈₎{6}) ⨁ res8₍₈₎{7})
              ⎪ 6: CF := ((extu @[eax₍₃₂₎]₁ 9) + (extu eax₍₃₂₎{0,7} 9)){8}
              ⎪ 7: @[eax₍₃₂₎]₁ := res8₍₈₎
              ⎩ 8: goto ({0x00000002; 32}, 0)

Expected output:
Something like this BAP code:

  v1 := mem32[pad:32[low:32[EAX]], el]:u8
  v2 := low:8[low:32[EAX]]
  AF := 0x10:8 = (0x10:8 & (((mem32[pad:32[low:32[EAX]], el]:u8) ^ v1) ^ v2))

System Info

OS:

# uname -a
Linux ubuntu 4.10.0-28-generic #32-Ubuntu SMP Fri Jun 30 05:32:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.04
DISTRIB_CODENAME=zesty
DISTRIB_DESCRIPTION="Ubuntu 17.04"

BINSEC: 20170301 0.1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions