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. --------------------------------------------------------------------------