From : Joe Koss 1:142/8076
--------------------------------------------------------------------------
AAD - D5 IMM8 - ASCII Adjust before Division
Undocumented: Available to all Intel x86 processors
Useful in production source code.
AAD
Flags: ASCII Adjust before Division
+-+-+-+-+-+-+-+-+-+ +----------+----------+
|O|D|I|T|S|Z|A|P|C| | 11010101 | DATA |
+-+-+-+-+-+-+-+-+-+ +----------+----------+
|+| | | |+|+|+|+|+| | D5 | IMM8 |
+-+-+-+-+-+-+-+-+-+ +----------+----------+
This instruction is the multiplication counterpart to AAM. As is the
case with AAM, AAD uses the second byte as an operand. This operand is
the multiplicand for AAD. Like AAM, AAD provides a way to execute a MUL
IMM8 that is unavailable through any other means in the CPU. Unlike MUL,
or IMUL, AAD sets all of the CPU status flags according to the result.
Intel states that the Overflow Flag (OF), Auxiliary carry Flag (AF), and
Carry Flag (CF) are undefined. This assertion is incorrect. These flags
are fully defined, and are set consistently with respect to any other
integer operations. And again, like AMM, beginning with the Pentium,
Intel has finally acknowledged the existence of the second byte of this
instruction as its operand. Intel says:
"Note: imm8 has the value of the instruction's second byte. The second
byte under normally assembly [sic] of this instruction will be 0A,
however, explicit modification of this byte will result in the operation
described above and may alter results."
This instruction exists in this form on all Intel x86 processors. See
the file AAD.ASM for diagnostics source code for this instruction.
----------------------------------------------------------------------------
AAM - D4 IMM8 - ASCII Adjust after Multiplication
Undocumented: Available to all Intel x86 processors.
Useful in production source code.
AAM
Flags: ASCII Adjust after Multiply
+-+-+-+-+-+-+-+-+-+ +----------+----------+
|O|D|I|T|S|Z|A|P|C| | 11010100 | DATA |
+-+-+-+-+-+-+-+-+-+ +----------+----------+
| | | |+|+|+| | D4 | IMM8 |
+-+-+-+-+-+-+-+-+-+ +----------+----------+
AAM is shown as a two byte encoding used to divide AX by 10, putting the
quotient in AH, and the remainder in AL. However, AAM is listed in the
op code map as a single byte instruction. This leads one to wonder why a
two-byte opcode is listed in the single-byte opcode map. In reality, the
second byte is an undocumented operand to AAM. The operand is the
divisor. In its documented incarnation, AAM is encoded as D4 0A. The
operand 0A is the divisor. This divisor can be changed to any value
between 0 and FF. Using AAM in this manner is useful -- as it extends
the CPU instruction set to include a DIV IMM8 instruction that is not
available from any other form of the DIV instruction. The extended form
of the AAM instruction is also useful because it sets the flags register
according to the results, unlike the DIV or IDIV instruction. According
to Intel documentation, SF, ZF, and PF flags are set according to the
result, while OF, AF, and CF are undefined. However, if AAM were used
strictly as documented, then the Sign Flag (SF) could not be set under
any circumstances, since anything divided by 10 will leave a remainder
between 0 and 9. Obviously the remainder could never be between 128 and
255 (or -1 and -128 if you prefer) if used only as documented. Since AAM
divides an 8 bit number by another 8-bit number, a carry or overflow
could never occur. Therefore CF and OF always=0. Intel claims they are
undefined, but my observations are consistent with my theory. Contrary
to documentation, AAM will generate exceptions in real mode, protected
mode, and V86 mode. AAM can only generate Exception 0 -- divide by 0.
Finally, in the Pentium User's Manual, this heretofore undocumented form
of AMM is described. Intel says:
"Note: imm8 has the value of the instruction's second byte. The second
byte under normally assembly [sic] of this instruction will be 0A,
however, explicit modification of this byte will result in the operation
described above and may alter results."
----------------------------------------------------------------------------
SALC - D6 - Set AL on Carry
An undocumented op code that performs an operation common to every
Assembly language subroutine to C and many other higher level languages.
This instruction is a C programmers 'dream' instruction for interfacing
to assembly language.
Undocumented: Available to all Intel x86 processors
Useful in production source code.
SALC
Flags: SET Carry flag to AL
+-+-+-+-+-+-+-+-+-+ +----------+
|O|D|I|T|S|Z|A|P|C| | 11010110 |
+-+-+-+-+-+-+-+-+-+ +----------+
| | | | | | | | | | | D6 |
+-+-+-+-+-+-+-+-+-+ +----------+
The name SALC simply stands for SET the Carry flag in AL. This
instruction is categorized as an undocumented single-byte proprietary
instruction. Intel claims it can be emulated as a NOP. Hardly a NOP,
this instruction sets AL=FF if the Carry Flag is set (CF=1), or resets
AL=00 if the Carry Flag is clear (CF=0). It can best be emulated as SBB
AL,AL. SALC doesn't change any flags, where SBB AL,AL does. This
instruction is most useful to high-level language programmers whose
programs call assembly language, and expect AL to indicate success or
failure. Since it is convenient for assembly language programs to return
status in the CF, this instruction will convert that status to a form
compatible with high level languages.
Over the years, this instruction has been given many names by various
discoverers. I originally gave it the name SETCAL, but the most common
name I've seen in print is SETALC. The name given above, SALC is an
official Intel name. While perusing the P6 opcode map, I always check
for known, undocumented opcodes. After weeding through the map for many
minutes, my patience and perseverance paid off. I found the opcode, and
its name. Intel's name for this opcode is SALC. This would indicate that
Intel plans to officially document this instruction, beginning with the
P6.
--------------------------------------------------------------------------