Some undocumented instruction updates
This commit is contained in:
parent
368370a4ea
commit
025b1abb93
19 changed files with 2531 additions and 1582 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: AAA"
|
||||
permalink: /docs/x86/ops/aaa/
|
||||
permalink: /docs/x86/ops/AAA/
|
||||
---
|
||||
|
||||
AAA (0x37)
|
||||
204
docs/x86/ops/AAD/AAD.ASM
Normal file
204
docs/x86/ops/AAD/AAD.ASM
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
;
|
||||
; Saved on February 16, 2015 from http://www.rcollins.org/ftp/source/aad/aad.asm
|
||||
;
|
||||
.386p
|
||||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; AAD.ASM Copyright (c) 1991, 1995-Present, Robert Collins
|
||||
;
|
||||
; You have my permission to copy and distribute this software for
|
||||
; non-commercial purposes. Any commercial use of this software or
|
||||
; source code is allowed, so long as the appropriate copyright
|
||||
; attributions (to me) are intact, *AND* my email address is properly
|
||||
; displayed.
|
||||
;
|
||||
; Basically, give me credit, where credit is due, and show my email
|
||||
; address.
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; Robert R. Collins email: rcollins@x86.org
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
.model small
|
||||
.code
|
||||
.286
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Interrupt vector segment
|
||||
;-----------------------------------------------------------------------------
|
||||
ABS0 segment at 0
|
||||
org 0*4
|
||||
Orig_INT0 label word
|
||||
ABS0 ends
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Local stack frame variable(s)
|
||||
;-----------------------------------------------------------------------------
|
||||
INT0 equ [bp-4]
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Instruction macro definition
|
||||
;-----------------------------------------------------------------------------
|
||||
AADI MACRO VALUE
|
||||
db 0d5h,VALUE
|
||||
ENDM
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
TEST_AAD proc near ; Test AAD IMMED08 instruction functionality.
|
||||
;-----------------------------------------------------------------------------
|
||||
; AAD:
|
||||
; {
|
||||
; AL = AH*IMMED08 + AL
|
||||
; AH = 0
|
||||
; CF = AL[b7] Overflow?
|
||||
; OF = AL[b7] set, but not overflow? or AL[b7] overflow, but not set?
|
||||
; AF = AL[b3] overflow, or AL[b3] borrow?
|
||||
; SF = AL[b7]=1?
|
||||
; ZF = AL==0?
|
||||
; PF = Even/Odd parity
|
||||
; }
|
||||
; Input: None
|
||||
; Output: BX = Bit mask of results (3FFF if all tests passed)
|
||||
; [b13] = 1, NS flag test passed
|
||||
; [b12] = 1, SF flag test passed
|
||||
; [b11] = 1, NZ flag test passed
|
||||
; [b10] = 1, ZF flag test passed
|
||||
; [b09] = 1, PO flag test passed
|
||||
; [b08] = 1, PE flag test passed
|
||||
; [b07] = 1, AF (test 2) flag test passed
|
||||
; [b06] = 1, AF (test 1) flag test passed
|
||||
; [b05] = 1, NA flag test passed
|
||||
; [b04] = 1, OF (test 2) flag test passed
|
||||
; [b03] = 1, NO flag test passed
|
||||
; [b02] = 1, OF (test 1) flag test passed
|
||||
; [b01] = 1, CY flag test passed
|
||||
; [b00] = 1, NC flag test passed
|
||||
; Register(s) modified: AX, BX, CX
|
||||
;-----------------------------------------------------------------------------
|
||||
xor bx,bx ; clear result flags
|
||||
xor cx,cx
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test Carry Flag set. According to Intel, CF is undefined after AAD, but
|
||||
; should be set according to the results. Since this is an arithmatic
|
||||
; operation, CF should be set according to the results. Let's find out!
|
||||
;-----------------------------------------------------------------------------
|
||||
mov ax,3300h ; set AH=51, AL=0 and perform 51*5.
|
||||
AADI 5 ; result should not produce a CF
|
||||
jc @F ; oops
|
||||
or bl,1 ; set NC passed
|
||||
@@: mov ax,3301h ; set AH=51, AL=1 and perform
|
||||
AADI 5 ; (55*5)+1 should set CF
|
||||
jnc @F ; oops, didn't work
|
||||
or bl,2 ; set CF passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test Overflow Flag set. There are two ways the OF can be set:
|
||||
; 1) If AL[b7] is set, but doesn't overflow into CF;
|
||||
; 2) If AL[b7] overflows, but doesn't get set.
|
||||
;-----------------------------------------------------------------------------
|
||||
; 1) If AL[b7] is set, but doesn't overflow into CF;
|
||||
;-----------------------------------------------------------------------------
|
||||
mov ax,2a02h ; perform (42*3)+2 = 128, should set
|
||||
AADI 3 ; OF.
|
||||
jno @F ; oops, didn't work
|
||||
or bl,4 ; set OF passed
|
||||
@@: mov ax,8080h ; perform (128*2)+128, should not set
|
||||
AADI 2 ; OF because it sets CF, & AL[b7]
|
||||
jo @F ; oops, didn't work
|
||||
or bl,8 ; set NO passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; 2) If AL[b7] overflows, but doesn't get set.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,8080h ; perform (128*2)+128, should not set
|
||||
AADI 1 ; OF because it sets CF, & AL[b7]
|
||||
jno @F ; oops, didn't work
|
||||
or bl,10h
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test Auxiliary carry Flag (AF) set. AF is set in two ways:
|
||||
; 1) If there is a carry out of bit3;
|
||||
; 2) If there is a borrow out of bit3.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,2200h ; perform (34*5)+0, should not set
|
||||
AADI 5 ; AM because no carry from bit3
|
||||
lahf ; get flags
|
||||
test ah,10h ; AF set?
|
||||
jnz @F ; yes, must have been a mistake
|
||||
or bl,20h ; set NA flag passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; 1) If there is a carry out of bit3;
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,2208h ; perform (34*5)+8, should set AF
|
||||
AADI 5 ; because a bit3 will carry
|
||||
lahf ; get flags
|
||||
test ah,10h ; AF set?
|
||||
jz @F ; nope, oops
|
||||
or bl,40h ; set AF flag passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; 2) If there is a borrow out of bit3.
|
||||
; (This may not be an accurate test of borrowing out of bit 3, because
|
||||
; this test adds a -8 to the result of the multplication. In other
|
||||
; words, the addition algorithm is still used, not the subtraction
|
||||
; algorithm -- if they are even different in the first place.)
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,22f8h ; perform (34*5)-8, should set AF
|
||||
AADI 5 ; because a bit3 will borrow
|
||||
lahf ; get flags
|
||||
test ah,10h ; AF set?
|
||||
jz @F ; nope, oops
|
||||
or bl,80h ; set AF flag passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test EVEN and ODD parity by generating results in the low byte that
|
||||
; contain even and odd parity respectively.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,0a00h ; 10*17+0 which is EVEN parity
|
||||
AADI 11h
|
||||
jpo @F ; didn't generate even parity
|
||||
or bh,1 ; set even parity flag passed
|
||||
@@: mov ax,0a01h ; 10*17+1 which is ODD parity
|
||||
AADI 11h
|
||||
jpe @F ; didn't generate odd parity
|
||||
or bh,2 ; set odd parity flag passed
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test ZERO FLAG by generating results that produce a zero, and non-zero.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov ax,0880h ; 8*16+128 will generate a zero result
|
||||
AADI 10h ; This should force ZF=1
|
||||
jnz @F ; didn't work as expected
|
||||
or bh,4
|
||||
@@: mov ax,0881h ; 8*16+129 will be non-zero
|
||||
AADI 10h ; This should force ZF=0,
|
||||
jz @F ; didn't work as expected
|
||||
or bh,8
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test Sign Flag by generating results whose highest bit is on.
|
||||
; I'll try and do this in a manner that doesn't set OF.
|
||||
;-----------------------------------------------------------------------------
|
||||
mov ax,80c0h ; (128*128)+192 will generate SF
|
||||
AADI 80h ; without generating OF.
|
||||
jns @F ; oops
|
||||
or bh,10h ; set SF flag passed
|
||||
@@: mov ax,8040h ;
|
||||
AADI 80h
|
||||
js @F
|
||||
or bh,20h
|
||||
@@: ret
|
||||
Test_AAD endp
|
||||
|
||||
end
|
||||
|
||||
|
||||
39
docs/x86/ops/AAD/README.md
Normal file
39
docs/x86/ops/AAD/README.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: AAD"
|
||||
permalink: /docs/x86/ops/AAD/
|
||||
---
|
||||
|
||||
AAD (0xD5)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/AAD.html](http://www.rcollins.org/secrets/opcodes/AAD.html):
|
||||
|
||||
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.
|
||||
|
||||
See [AAD.ASM](AAD.ASM) for the source code mentioned above.
|
||||
221
docs/x86/ops/AAM/AAM.ASM
Normal file
221
docs/x86/ops/AAM/AAM.ASM
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
;
|
||||
; Saved on February 16, 2015 from http://www.rcollins.org/ftp/source/aam/aam.asm
|
||||
;
|
||||
.386p
|
||||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; AAM.ASM
|
||||
;
|
||||
; Copyright (c) 1991, 1995-Present Robert Collins
|
||||
;
|
||||
; You have my permission to copy and distribute this software for
|
||||
; non-commercial purposes. Any commercial use of this software or
|
||||
; source code is allowed, so long as the appropriate copyright
|
||||
; attributions (to me) are intact, *AND* my email address is properly
|
||||
; displayed.
|
||||
;
|
||||
; Basically, give me credit, where credit is due, and show my email
|
||||
; address.
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; Robert R. Collins email: rcollins@x86.org
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
.model small
|
||||
.code
|
||||
.286
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Interrupt vector segment
|
||||
;-----------------------------------------------------------------------------
|
||||
ABS0 segment at 0
|
||||
org 0*4
|
||||
Orig_INT0 label word
|
||||
ABS0 ends
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Local stack frame variable(s)
|
||||
;-----------------------------------------------------------------------------
|
||||
INT0 equ [bp-4]
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Instruction macro definition
|
||||
;-----------------------------------------------------------------------------
|
||||
AAMI MACRO VALUE
|
||||
db 0d4h,VALUE
|
||||
ENDM
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
TEST_AAM proc near ; Test AAM IMMED08 instruction functionality.
|
||||
;-----------------------------------------------------------------------------
|
||||
; Input: None
|
||||
; Output: BX = Bit mask of results (3FF if all tests passed)
|
||||
; [b15..b10] = Unused
|
||||
; [b9] = 1, Carry Flag test passed
|
||||
; [b8] = 1, Overflow Flag test passed
|
||||
; [b7] = 1, Auxiliary carry Flag test passed
|
||||
; [b6] = 1, INT0 exception passed
|
||||
; [b5] = 1, ZF flag test passed
|
||||
; [b4] = 1, NZ flag test passed
|
||||
; [b3] = 1, NS flag test passed
|
||||
; [b2] = 1, SF flag test passed
|
||||
; [b1] = 1, PE flag test passed
|
||||
; [b0] = 1, PO flag test passed
|
||||
; Register(s) modified: AX, BX, CX, SI
|
||||
;-----------------------------------------------------------------------------
|
||||
xor bx,bx ; clear result flags
|
||||
xor cx,cx
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test EVEN and ODD parity by generating results in the low byte that
|
||||
; contain even and odd parity respectively.
|
||||
;-----------------------------------------------------------------------------
|
||||
mov al,0fbh ; 251/252 leave remainder=251, whose
|
||||
; parity=ODD.
|
||||
AAMI 0FCh ; generate odd parity
|
||||
jpe @F ; oops odd parity not set
|
||||
or bl,1 ; set even parity flag
|
||||
@@: AAMI 0F1h ; 251/241 leaves remainder=10, whose
|
||||
; parity=EVEN
|
||||
jpo @F ; oops even parity
|
||||
or bl,2 ; set odd parity flag
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test Sign flag by generating results in the low byte whose bit7=1. This
|
||||
; is easily done by putting 80h in AL, and dividing by a number larger than
|
||||
; 80h. The remainder will always be 80h, and therefore the sign flag is set.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov al,080h ; 128/255 leaves remainder=128, whose
|
||||
AAMI 0ffh ; Sign flag=1 (bit7=1)
|
||||
jns @F ; oops no SF!
|
||||
or bl,4 ; set SF flag
|
||||
@@: AAMI 80h ; 128/128 leaves remainder=0, whose
|
||||
js @F ; sign flag=0 (bit7=0)
|
||||
or bl,8 ; set NS flag
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test ZERO flag by generating results in the low byte as ZERO, and NON-ZERO.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov al,0f0h ; 240/127 leaves remainder=113, which
|
||||
AAMI 7Fh ; is obviously not 0.
|
||||
jz @F ; oops, ZF!
|
||||
or bl,10h ; set NF flag
|
||||
@@: AAMI 113d ; 113/113 leaves remainder=0, which is
|
||||
jnz @F ; obviously 0!
|
||||
or bl,20h ; set ZF flag
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test that AAM 0 (divide by 0) will generate the appropriate CPU exception
|
||||
; (exception 0). This can be tested by setting up a simple INT0 handler, and
|
||||
; try to divide by 0. If the execption occured, then success.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: enter 4,0 ; create stack frame
|
||||
mov word ptr INT0,offset INT0_handler
|
||||
mov INT0[2],cs ; save current CS to restore later
|
||||
call set_INT0_vector ; set pointer to our INT6 handler
|
||||
AAMI 0 ; generate INT0 exception
|
||||
jcxz @F ; if CX=0, then an error occurred
|
||||
or bl,40h ; set success flag
|
||||
@@: call set_INT0_vector ; restore original INT0 vector
|
||||
leave ; restore stack frame
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Test unaffected flags will cycle through every possible combination of
|
||||
; AAM, and test that none of the "unaffected" flags are changed. For
|
||||
; brevity of source code, I'm going to do one of the biggest no-no's in
|
||||
; programming...I'm going to write self modifying code.
|
||||
;-----------------------------------------------------------------------------
|
||||
; First test the Auxiliary carry Flag (AF). If AF gets set, then the test
|
||||
; fails.
|
||||
;-----------------------------------------------------------------------------
|
||||
mov si,offset @AF[1] ; get address of operand to AAM
|
||||
mov cx,1 ; start with AAM 01
|
||||
@@: mov al,ch
|
||||
mov cs:[si],cl ; modify op code
|
||||
jmp short @AF ; go
|
||||
@AF: AAMI 00 ; starting sequence
|
||||
lahf ; get flags register
|
||||
test ah,10h ; auxiliary flag set?
|
||||
jnz short @F ; yes
|
||||
add ch,1 ; try next dividend
|
||||
adc cl,0 ; try next divisor
|
||||
jnc @B ; continue
|
||||
or bl,80h ; set success flag
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Second, test the Overflow Flag (OF). If OF gets set, then the test fails.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov si,offset @OF[1] ; get address of operand to AAM
|
||||
mov cx,1 ; start with AAM 01
|
||||
@@: mov al,ch
|
||||
mov cs:[si],cl ; modify op code
|
||||
jmp short @OF ; go
|
||||
@OF: AAMI 00 ; starting sequence
|
||||
jo short @F ; test failed
|
||||
add ch,1 ; try next dividend
|
||||
adc cl,0 ; try next divisor
|
||||
jnc @B ; continue
|
||||
or bh,01h ; set success flag
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Finally, test the Carry Flag (CF). If CF gets set, then the test fails.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@: mov si,offset @CF[1] ; get address of operand to AAM
|
||||
mov cx,1 ; start with AAM 01
|
||||
@@: mov al,ch
|
||||
mov cs:[si],cl ; modify op code
|
||||
jmp short @CF ; go
|
||||
@CF: AAMI 00 ; starting sequence
|
||||
jc short @F ; test failed
|
||||
add ch,1 ; try next dividend
|
||||
adc cl,0 ; try next divisor
|
||||
jnc @B ; continue
|
||||
or bh,02h ; set success flag
|
||||
@@: ret ; split
|
||||
Test_AAM endp
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Set the INT6 vector by exchanging it with the one currently on the stack.
|
||||
;-----------------------------------------------------------------------------
|
||||
set_INT0_vector:
|
||||
push ds
|
||||
push ABS0 ; save interrupt vector segment
|
||||
pop ds ; make DS=INT vector segment
|
||||
|
||||
ASSUME DS:ABS0
|
||||
mov dx,Orig_INT0; ; get offset if INT0 handler
|
||||
xchg INT0,dx ; set new INT0 offset
|
||||
mov Orig_INT0,dx
|
||||
mov dx,Orig_INT0[2] ; get segment of INT0 handler
|
||||
xchg INT0[2],dx ; set new INT0 segment
|
||||
mov Orig_INT0[2],dx
|
||||
pop ds ; restore segment register
|
||||
ret ; split
|
||||
ASSUME DS:NOTHING
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; INT0 handler sets a semaphore (CX=FFFF) and adjusts the return address to
|
||||
; point past the invalid opcode.
|
||||
;-----------------------------------------------------------------------------
|
||||
INT0_handler:
|
||||
enter 0,0 ; create new stack frame
|
||||
dec cx ; make CX=FFFF
|
||||
add word ptr ss:[bp][2],2 ; point past invalid opcode
|
||||
leave
|
||||
iret
|
||||
|
||||
end
|
||||
|
||||
|
||||
51
docs/x86/ops/AAM/README.md
Normal file
51
docs/x86/ops/AAM/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: AAM"
|
||||
permalink: /docs/x86/ops/AAM/
|
||||
---
|
||||
|
||||
AAD (0xD4)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/AAM.html](http://www.rcollins.org/secrets/opcodes/AAM.html):
|
||||
|
||||
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 |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+----------+
|
||||
|0| | | |+|+|0|+|0| | D4 | IMM8 |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+----------+
|
||||
|
||||
AAM is shown as a two byte encoding used to divide AL 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.
|
||||
|
||||
This instruction exists in this form on all Intel x86 processors. See the file AAM.ASM for diagnostics source code
|
||||
for this instruction.
|
||||
|
||||
See [AAM.ASM](AAM.ASM) for the source code mentioned above.
|
||||
65
docs/x86/ops/ICEBP/README.md
Normal file
65
docs/x86/ops/ICEBP/README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: ICEBP"
|
||||
permalink: /docs/x86/ops/ICEBP/
|
||||
---
|
||||
|
||||
ICEBP (0xF1)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html):
|
||||
|
||||
An undocumented op code that will make debugging run-time code on an ICE easier. Normally, to set an arbitrary
|
||||
breakpoint in a program which was loaded by an operating system, you must perform a laborious task of figuring out
|
||||
where your program was loaded in memory. Follow that process with an equally laborious task of calculating the
|
||||
offset in memory which corresponds to the desired breakpoint. This process is exacerbated by programs which use
|
||||
many segments, especially many code segments. Now for one final complication, consider that your program switches
|
||||
from real mode, to protected mode, with paging enabled, and you are not using a 1-to-1 mapping of physical to
|
||||
virtual memory. You want to talk about a nightmare just to figure out where to set a breakpoint?
|
||||
|
||||
All of these problems are eliminated, simply by using this instruction -- provided you know its caveats.
|
||||
|
||||
Undocumented: Available to all 80386-class (and above)
|
||||
processors as described herein.
|
||||
May be available to 80286 processors, but
|
||||
implemented in a different manner.
|
||||
Useful to BONDOUT (ICE) processors.
|
||||
Especially useful during ICE debugging.
|
||||
Useful in production source code.
|
||||
ICEBP
|
||||
Flags: ICE Break Point
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+
|
||||
|O|D|I|T|S|Z|A|P|C| | 11110001 |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+
|
||||
| | | | | | | | | | | F1 |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+
|
||||
|
||||
The name ICEBP was given by a pre-production Intel ICE that had the ability to disassemble undocumented op codes.
|
||||
The name ICEBP is a misnomer because the instruction is actually a single byte single-step exception (INT-01).
|
||||
|
||||
How you use ICEBP depends upon whether or not you are using an 80386 ICE, Intel486 ICE, or Pentium ICE. For the
|
||||
purposes of this article, usage of ICEBP on 80386 and Intel486 are identical. Pentium enables ICEBP a little
|
||||
differently than its predecessors.
|
||||
|
||||
Two effects of ICEBP -- 80386 and Intel486
|
||||
|
||||
ICEBP has two operational effects: When Interrupt Redirection (IR) is disabled, ICEBP acts as a single byte INT 01.
|
||||
When this instruction occurs, it invokes the standard INT 01 handler. Unlike the single step exception (Trap Flag=1),
|
||||
this instruction does not set the trap flag on the stack image, nor modifies the trap flag on the stack image.
|
||||
Therefore, upon termination of the INT 01 handler, execution continues without further occurrences of the single
|
||||
step breakpoints.
|
||||
|
||||
When Interrupt Redirection is enabled, ICEBP will attempt to invoke the hardware breakpoint handler associated with
|
||||
an In Circuit Emulator (ICE). If the processor is a production CPU, the processor will hang. If the processor is a
|
||||
BONDOUT CPU attached to an ICE, ICEBP will cause the ICE to break from emulation. On an Intel ICE, the message
|
||||
"Unknown Breakpoint at address xxxx:xxxx:xxxxxxxx" appears on the screen.
|
||||
|
||||
There are two ways to enable Interrupt Redirection. It can be done by directly programming DR7 (see "Undocumented
|
||||
Bits in DR7"), or this bit can be set (indirectly) using an ICE. To set this bit using an ICE, you must first be in
|
||||
HALT mode. Any "go til" command that uses the debug registers will enable Interrupt Redirection. For example,
|
||||
"go til 1234:5678 execute," "go til 1025:3245 write," or simply "go til 0 p" will enable Interrupt Redirection.
|
||||
This work because the ICE actually uses the debug registers to trap debug exceptions. Of course, this directly
|
||||
implies that any time the ICE uses the debug registers to signify break points, and emulation halts, it does so
|
||||
following an INT 01 to the ICE break point handler (since interrupt redirection is enabled).
|
||||
221
docs/x86/ops/LOADALL/README.md
Normal file
221
docs/x86/ops/LOADALL/README.md
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: LOADALL"
|
||||
permalink: /docs/x86/ops/LOADALL/
|
||||
---
|
||||
|
||||
LOADALL386 (0x070F)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/LOADALL.html](http://www.rcollins.org/secrets/opcodes/LOADALL.html):
|
||||
|
||||
(LOADALL) An undocumented op code used by ICE host software and diagnostics software to test CPU functionality.
|
||||
This instruction has the ability to bypass the entire protection checking mechanism in the CPU, and therefore can
|
||||
be used to test many aspects of CPU behavior that can't be duplicated by any other software means.
|
||||
|
||||
Read LOADALL magazine article and download LOADALL demo source code.
|
||||
|
||||
Undocumented: Available on all 80386 processors.
|
||||
Useful for diagnostics purposes on production
|
||||
CPU's.
|
||||
Useful for ICE BONDOUT CPU's to return the
|
||||
processor to EMUlation state.
|
||||
LOADALL
|
||||
Flags: Loads the entire CPU state
|
||||
All flags set according to +----------+----------+
|
||||
the LOADALL flags image. | 00001111 | 00000111 |
|
||||
+----------+----------+
|
||||
| 0F | 07 |
|
||||
+----------+----------+
|
||||
Input: ES:EDI points to the Clocks: 122
|
||||
LOADALL register image. Bus Cycles: 51
|
||||
LOADALL loads the entire CPU state from a table pointed to by
|
||||
ES:EDI. At the completion of LOADALL, the CPU state is defined
|
||||
according to this table. No protection checks are performed
|
||||
against values in the table, and LOADALL can generate no
|
||||
exceptions in real mode, or in protected mode at IOPL 0.
|
||||
Attempting to execute LOADALL at any other privilege level will
|
||||
generate an exception 13.
|
||||
There are three types of structures in the LOADALL image:
|
||||
1) 32-bit CPU registers entries;
|
||||
2) 16-bit segment registers (zero-extended to 32-bits);
|
||||
3) 96-bit segment descriptor cache entries.
|
||||
The segment register entries have the following format:
|
||||
SREG STRUC
|
||||
REG_VAL DW ? ; low 16-bits defined
|
||||
DW 0 ; high 16-bits=0
|
||||
ENDS
|
||||
The segment descriptor cache entires have the following format:
|
||||
DESC_CACHE STRUC
|
||||
DB 0 ; b[00-07] not used
|
||||
S_USE DB ? ; b[14] operand size
|
||||
S_Access DB ? ; b[16-23] Access Rights
|
||||
DB 0 ; b[24-31] not used
|
||||
S_Addr DD ? ; Segment Address in memory
|
||||
S_Limit DD ? ; Segment size limit
|
||||
ENDS
|
||||
The LOADALL tables is organized as follows:
|
||||
;----------------------------------------------------------------
|
||||
; LOADALL table pointed to by ES:EDI
|
||||
;----------------------------------------------------------------
|
||||
Offset Description Size Value
|
||||
====== =========== ==== =====
|
||||
[00] CR0 DD ?
|
||||
[04] EFLAGS DD ?
|
||||
[08] EIP DD ?
|
||||
[0C] EDI DD ?
|
||||
[10] ESI DD ?
|
||||
[14] EBP DD ?
|
||||
[18] ESP DD ?
|
||||
[1C] EBX DD ?
|
||||
[20] EDX DD ?
|
||||
[24] ECX DD ?
|
||||
[28] EAX DD ?
|
||||
[2C] DR6 DD ?
|
||||
[30] DR7 DD ?
|
||||
[34] TR_REG SREG <?>
|
||||
[38] LDT_REG SREG <?>
|
||||
[3C] GS_REG SREG <?>
|
||||
[40] FS_REG SREG <?>
|
||||
[44] DS_REG SREG <?>
|
||||
[48] SS_REG SREG <?>
|
||||
[4C] CS_REG SREG <?>
|
||||
[50] ES_REG SREG <?>
|
||||
[54] TSS_DESC DESC_CACHE <?,?,?>
|
||||
[60] IDT_DESC DESC_CACHE <0,?,?>
|
||||
[6C] GDT_DESC DESC_CACHE <0,?,?>
|
||||
[78] LDT_DESC DESC_CACHE <?,?,?>
|
||||
[84] GS_DESC DESC_CACHE <?,?,?>
|
||||
[90] FS_DESC DESC_CACHE <?,?,?>
|
||||
[9C] DS_DESC DESC_CACHE <?,?,?>
|
||||
[A8] SS_DESC DESC_CACHE <?,?,?>
|
||||
[B4] CS_DESC DESC_CACHE <?,?,?>
|
||||
[C0] ES_DESC DESC_CACHE <?,?,?>
|
||||
[CC] LENGTH OF TABLE
|
||||
The following two diagrams take a closer look at fields within
|
||||
the LOADALL table:
|
||||
1) the descriptor cache register;
|
||||
2) the access rights within the descriptor cache register.
|
||||
;---------------------------------------------------------------------
|
||||
; Segment descriptor cache register
|
||||
;
|
||||
; 9 6 3 2 1 1 0 0
|
||||
; 5 3 1 3 5 3 7 0
|
||||
; +--------------+---------------------+---+---------------+---+---+
|
||||
; | 32-bit limit | 32-bit base address | 0 | Access Rights | 0 | 0 |
|
||||
; +--------------+---------------------+---+---------------+---+---+
|
||||
;
|
||||
;---------------------------------------------------------------------
|
||||
; 386 Descriptor Cache Access Rights
|
||||
;
|
||||
; ++++++++----------------------------- 0=Undefined
|
||||
; |||||||| +--------------------------- Present 0=No 1=Yes
|
||||
; |||||||| |++------------------------- Descriptor privelege level
|
||||
; |||||||| |||+------------------------ System Desc. 0=Sys 1=Code/Data
|
||||
; |||||||| ||||+++--------------------- Type(*)
|
||||
; |||||||| ||||||+-----------------------Read/Write 0=R/O 1=R/W
|
||||
; |||||||| |||||+|-----------------------Expansion 0=Up 1=Dwn
|
||||
; |||||||| ||||+||-----------------------Executable 0=No 1=Yes*
|
||||
; |||||||| ||||||| 000=Read Only
|
||||
; |||||||| ||||||| 001=Read/Write
|
||||
; |||||||| ||||||| 010=Read Only, Expand down
|
||||
; |||||||| ||||||| 011=Read/Write, Expand down
|
||||
; |||||||| ||||||| 100=Execute only
|
||||
; |||||||| ||||||| 101=Execute/Read
|
||||
; |||||||| ||||||| 110=Execute only, conforming
|
||||
; |||||||| ||||||| 111=Execute/Read, conforming
|
||||
; |||||||| |||||||+-------------------- Accessed
|
||||
; |||||||| |||||||| +------------------ 0=Undefined (was G bit)
|
||||
; |||||||| |||||||| |+----------------- Default operand size(+)
|
||||
; |||||||| |||||||| || 0=16-bit operands
|
||||
; |||||||| |||||||| || 1=32-bit operands
|
||||
; |||||||| |||||||| ||
|
||||
; |||||||| |||||||| ||++++++-++++++++-- 0=Undefined
|
||||
; |||||||| |||||||| |||||||| ||||||||
|
||||
; |||||||| |||||||| |||||||| ||||||||
|
||||
; 3||||||||2||||||||1||||||||0||||||||0 Bit
|
||||
; 1||||||||3||||||||5||||||||7||||||||0 Offset
|
||||
; +++++++++++++++++++++++++++++++++++++
|
||||
; | Intel |22221111|11|Intel| Intel | (*) = CS can be marked as a R/W
|
||||
; |Reserved|32109876|54|Rsvd.|Reserved| data segment if LOADALL
|
||||
; +++++++++++++++++++++++++++++++++++++ is used to load register.
|
||||
; (+) = Only applicable for CS
|
||||
;
|
||||
;---------------------------------------------------------------------
|
||||
;---------------------------------------------------------------------
|
||||
; A closer look at the access rights field definitions:
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 Bit 2 2 2 2 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 Offset 3 2 1 0 9 8 7 6 5 4
|
||||
; +-+---+-+-----+-+-+-+-+ +-+---+-+-----+-+-+-+
|
||||
; |P|DPL|S|Type |A|0|G|D| |P|DPL|S| Type |G|D|
|
||||
; | | | |0| | | | | | | | | | | |1| | | | | | |
|
||||
; +-+---+-+-----+-+-+-+-+ +-+---+-+-----+-+-+-+
|
||||
; Bit:
|
||||
; P Present bit. 1=Present, 0=Not present.
|
||||
; This bit signals the CPU if the segment addressed by the
|
||||
; segment base address is actually present in memory.
|
||||
; DPL Descriptor Privilege Level: 0=highest, 3=lowest
|
||||
; S System descriptor: 0=Code, Data; 1=System descriptor
|
||||
; Type Segment Type: (S=0)
|
||||
; +-+-+-+
|
||||
; |X|Y|Z|
|
||||
; +-+-+-+
|
||||
; | | |
|
||||
; | | +-- Read/Write 0=Read-only 1=Read/Write
|
||||
; | +---- Expansion direction. 0=Expand up 1=Expand down
|
||||
; +------ Executable 0=Data Seg 1=Code Seg
|
||||
; Type Segment Type: (S=1)
|
||||
; 0000 = Reserved
|
||||
; 0001 = Available 286 TSS
|
||||
; 0010 = LDT
|
||||
; 0011 = Busy 286 TSS
|
||||
; 0100 = 286 Call Gate
|
||||
; 0101 = Task Gate
|
||||
; 0110 = 286 Interrupt Gate
|
||||
; 0111 = 286 Trap Gate
|
||||
; 1000 = Reserved
|
||||
; 1001 = Available 386, 486 TSS
|
||||
; 1010 = Reserved
|
||||
; 1011 = Busy 386, 486 TSS
|
||||
; 1100 = 386, 486 Call Gate
|
||||
; 1101 = Reserved
|
||||
; 1110 = 386, 486 Interrupt Gate
|
||||
; 1111 = 386, 486 Trap Gate
|
||||
; A Accessed (S=0) 0=Not Accessed 1=Accessed
|
||||
; The processor sets this bit when the descriptor is
|
||||
; accessed.
|
||||
; G Granularity 0=Byte 1=4k
|
||||
; When set, upon loading the limit field of the descriptor
|
||||
; cache register, the CPU shifts the limit by 12, and fills
|
||||
; in the 1st 12 bits with 1's as follows:
|
||||
; SHL LIMIT,12
|
||||
; OR LIMIT,0FFFh
|
||||
; D Default operand size 0=16-bit 1=32-bit
|
||||
; When set, the CPU interprets all operands, and effective
|
||||
; addresses as 32-bit values. When clear, all operands
|
||||
; and effective addresses are 16-bit values. This bit
|
||||
; is only applicable to the CS descriptor cache.
|
||||
;---------------------------------------------------------------------
|
||||
;---------------------------------------------------------------------
|
||||
; The definition of these bits is exactly as that of the access
|
||||
; rights in the descriptor table, with the following exceptions:
|
||||
; 1) The "PRESENT" bit becomes a valid bit. Using LOADALL, you
|
||||
; may load a descriptor cache register whose P bit is marked
|
||||
; not present (P=0). During normal CPU operaion, simply
|
||||
; loading the segment selector with a descriptor table entry
|
||||
; whose P=0 will cause an exception-11. This is different
|
||||
; that operating with LOADALL. LOADALL will let you load the
|
||||
; descriptor cache register with P=0. But any memory
|
||||
; reference using that segment selector will cause exception-
|
||||
; 13.
|
||||
; 2) The DPL field for SS & CS descriptors determine the CPL.
|
||||
; 3) The DPL field for DS, ES, FS, & GS should be 3.
|
||||
; 4) The Granularity (G) bit has no effect on the limit field
|
||||
; in the descriptor cache register
|
||||
; 5) A Code segment (CS) may be Read/Write/Executable by setting
|
||||
; the access rights as a Read/Write/Data segment. This will
|
||||
; even work in protected mode.
|
||||
;---------------------------------------------------------------------
|
||||
40
docs/x86/ops/SALC/README.md
Normal file
40
docs/x86/ops/SALC/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: SALC"
|
||||
permalink: /docs/x86/ops/SALC/
|
||||
---
|
||||
|
||||
SALC (0xD6)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/SALC.html](http://www.rcollins.org/secrets/opcodes/SALC.html):
|
||||
|
||||
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.
|
||||
47
docs/x86/ops/UMOV/README.md
Normal file
47
docs/x86/ops/UMOV/README.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
layout: page
|
||||
title: "x86 Instructions: UMOV"
|
||||
permalink: /docs/x86/ops/UMOV/
|
||||
---
|
||||
|
||||
UMOV (0x100F,0x110F,0x120F,0x130F)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html):
|
||||
|
||||
An undocumented op code used by ICE host software to perform memory cycles to the target system during HALT mode.
|
||||
|
||||
Undocumented: Available on all 80386/80486 processors.
|
||||
Useful only to BONDOUT (ICE) processors.
|
||||
UMOV
|
||||
Flags: User MOVE data
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+----------+-------------+
|
||||
|O|D|I|T|S|Z|A|P|C| | 00001111 | 000100dw | mod,reg,r/m |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+----------+-------------+
|
||||
| | | | | | | | | | | 0F | 1x | xx |
|
||||
+-+-+-+-+-+-+-+-+-+ +----------+----------+-------------+
|
||||
|
||||
UMOV is an acronym for User-MOVe. When the In-Circuit Emulator
|
||||
(ICE) is in HALT mode, the CPU performs no recognizable bus
|
||||
cycles. Since the '386 is a dynamic device, it must be executing
|
||||
some instructions during HALT, but it is not doing it in a way
|
||||
recognizable to a logic analyzer with a '386 probe attached.
|
||||
During HALT mode, the ICE differentiates between USER space and
|
||||
HOST space. The ICE is fetching, and performing all bus cycles
|
||||
to HOST memory space during HALT, and not USER space. Since the
|
||||
ICE differentiates between these two memory spaces, it needs a
|
||||
mechanism to access user memory space. That mechanism is UMOV.
|
||||
When a user request to view memory, or disassemble memory, the
|
||||
ICE executes UMOV instructions to get data from User space.
|
||||
If UMOV is executed by a user program, it will appear it is a
|
||||
alias for MOV.
|
||||
The field operands to UMOV are exactly the same as the MOV
|
||||
instruction. For example:
|
||||
d Direction. If set (d=1), do memory to register, or register
|
||||
to register; the reg field is the destination. If cleared
|
||||
(d=0), do register to memory; the reg field is the source.
|
||||
w Width. Selects the default data width. W=1 selects
|
||||
word width, according to the appropriate CPU operating mode,
|
||||
and/or size prefix override. W=0 selects 8-bit operands.
|
||||
Loading…
Reference in a new issue