Some undocumented instruction updates

This commit is contained in:
Jeff Parsons 2016-02-16 12:21:58 -08:00
commit 025b1abb93
19 changed files with 2531 additions and 1582 deletions

View file

@ -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
View 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

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

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

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

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

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

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