1

This is a print screen obtained from Visual Studio showing the apparent contradiction between VS2019 and the Intel's manuals.

enter image description here

Below you'll find the corresponding code for this x86 project:

.486
.model flat,stdcall
.stack 4096
ExitProcess proto, dwExitCode:dword

.code
main proc
    mov ah,0
    mov al,'6' ; AX = 0036h
    add al,'3' ; AX = 0069h                     ; Section 3.4.3.1 of Volume 1 of Intel's docs says the following regarding
                                                ; the AF (auxiliary flag):
                                                ;
                                                ; "Set if an arithmetic operation generates a carry or a borrow out of bit 3
                                                ;  of the result; cleared otherwise. This flag is used in binary-coded
                                                ;  decimal (BCD) arithmetic."
                                                ;
                                                ; Shouldn't the instruction above (add al, '3') set the AF flag to 1?
                                                ; If we look at the corresponding bits affected by this instruction we have:
                                                ;
                                                ;       7654 3210 >> Bit numbers
                                                ;       ---- ----
                                                ; 36h   0011 0110
                                                ; 33h   0011 0011
                                                ; AL    0110 1001   which shows that bit 3 had a carry from bit 2. Therefore,
                                                ;                   bit number 4 in the EFLAGS register (AF flag) should be
                                                ;                   set to 1. But that's not what the EFL shows below in the
                                                ;                   Registers window.
                                                ;
                                                ; What am I missing?

    aaa ; AX = 0069h (ASCII adjust result)

    invoke ExitProcess,0                        
main endp
end main
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Belloc
  • 6,318
  • 3
  • 22
  • 52
  • `0x9 + 0x6 = 0xf`, no carry out of the low 4 bits, so AF=0. AF is set according to carry **out of** bit 3, into bit 4. You're looking at the wrong bit-position, carry *in* to bit 3, out of the low 3 bits. AF is a "half carry" / nibble carry flag for BCD work, 4 bits per base-10 digit. – Peter Cordes Sep 27 '21 at 21:57
  • @PeterCordes Thanks for your comment. This is the answer to my question. Do you happen to know what is the logic behind the expression `AX := AX + 106H;` in the pseudo-code for the instruction AAA in Volume 2, Section 3.2 of Intel's Manual? – Belloc Sep 27 '21 at 23:23
  • 1
    That wraps the low nibble of the low digit into 0..9 by adding the extra 6 (16-10) to make a 4-bit binary integer wrap like a base-10 digit would have, and increments the high digit (unpacked with 1 digit per byte, that's why the mnemonic is "ASCII" not "decimal"). You could try it out for a few cases like `0x0407` + `0x0206` (47+26) with `add ax, cx` / `aaa` on paper and see how that correctly gives you `0x0703` (73) – Peter Cordes Sep 28 '21 at 00:42
  • 1
    And BTW, for individual instructions, a handy place to look them up is https://www.felixcloutier.com/x86/aaa, scraped from Intel's vol.2 manual. – Peter Cordes Sep 28 '21 at 00:44
  • @PeterCordes Finally the penny dropped and everything is clear to me with respect to `AX = AX + 106H;`. Thank you for your kind attention. – Belloc Sep 28 '21 at 18:41

0 Answers0