123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- x86dis.c
- Abstract:
- This module contains routines for disassembling x86 binary code.
- Author:
- Evan Green 21-Jun-2012
- Environment:
- Debugging client
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/types.h>
- #include "disasm.h"
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the meanings of some of size characters used in the encoding table.
- //
- #define X86_WIDTH_BYTE 'b'
- #define X86_WIDTH_WORD 'w'
- #define X86_WIDTH_LONG 'l'
- #define X86_WIDTH_LONGLONG 'q'
- #define X86_FLOATING_POINT_REGISTER 'f'
- //
- // Define the internal bitfields of the ModR/M and SIB byte.
- //
- #define X86_MOD_MASK 0xC0
- #define X86_REG_MASK 0x38
- #define X86_RM_MASK 0x07
- #define X86_MOD_SHIFT 6
- #define X86_REG_SHIFT 3
- #define X86_RM_SHIFT 0
- #define X86_SCALE_MASK 0xC0
- #define X86_INDEX_MASK 0x38
- #define X86_BASE_MASK 0x07
- #define X86_SCALE_SHIFT 6
- #define X86_INDEX_SHIFT 3
- #define X86_BASE_SHIFT 0
- //
- // Define some of the prefixes that can come at the beginning of an instruction.
- //
- #define X86_MAX_PREFIXES 4
- #define X86_OPERAND_OVERRIDE 0x66
- #define X86_ADDRESS_OVERRIDE 0x67
- #define X86_ESCAPE_OPCODE 0x0F
- #define X86_PREFIX_LOCK 0xF0
- #define X86_PREFIX_REP1 0xF2
- #define X86_PREFIX_REP2 0xF3
- #define X86_PREFIX_CS 0x2E
- #define X86_PREFIX_DS 0x3E
- #define X86_PREFIX_ES 0x26
- #define X86_PREFIX_SS 0x36
- //
- // This mask/value combination covers the FS prefix, GS prefix, Operand
- // override, and Address override.
- //
- #define X86_PREFIX_FS_GS_OVERRIDE_MASK 0xFC
- #define X86_PREFIX_FS_GS_OVERRIDE_VALUE 0x64
- //
- // For opcode groups with fewer than the maximum number of possible opcodes,
- // define how many opcodes each group does have.
- //
- #define X86_GROUP_4_INSTRUCTION_COUNT 2
- #define X86_GROUP_5_INSTRUCTION_COUNT 7
- #define X86_GROUP_6_INSTRUCTION_COUNT 6
- #define X86_GROUP_8_FIRST_INSTRUCTION 4
- #define X86_GROUP_9_ONLY_VALID_INSTRUCTION 1
- #define X86_INVALID_GROUP 99
- //
- // Define the sizes of the register name arrays.
- //
- #define X86_DEBUG_REGISTER_COUNT 8
- #define X86_SEGMENT_REGISTER_COUNT 6
- #define X86_REGISTER_NAME_COUNT 8
- //
- // Define the size of the working buffers.
- //
- #define X86_WORKING_BUFFER_SIZE 100
- //
- // Define the multiplication and shift opcodes that have 3 operands.
- //
- #define X86_OPCODE1_IMUL1 0x69
- #define X86_OPCODE1_IMUL2 0x6B
- #define X86_OPCODE2_SHLD1 0xA4
- #define X86_OPCODE2_SHLD2 0xA5
- #define X86_OPCODE2_SHRD1 0xAC
- #define X86_OPCODE2_SHRD2 0xAD
- //
- // Define some x87 floating point support definitions, constants used in
- // decoding an x87 coprocessor instruction.
- //
- #define X87_ESCAPE_OFFSET 0xD8
- #define X87_FCOM_MASK 0xF8
- #define X87_FCOM_OPCODE 0xD0
- #define X87_D9_E0_OFFSET 0xE0
- #define X87_DA_C0_MASK 0x38
- #define X87_DA_CO_SHIFT 3
- #define X87_FUCOMPP_OPCODE 0xE9
- #define X87_DB_C0_MASK 0x38
- #define X87_DB_C0_SHIFT 3
- #define X87_DB_E0_INDEX 4
- #define X87_DB_E0_MASK 0x7
- #define X87_DF_C0_MASK 0x38
- #define X87_DF_C0_SHIFT 3
- #define X87_DF_E0_INDEX 4
- #define X87_DF_E0_MASK 0x07
- #define X87_DF_E0_COUNT 3
- #define X87_REGISTER_TARGET "Rf"
- #define X87_ST0_TARGET "! st"
- #define X87_FLD_MNEMONIC "fld"
- #define X87_FXCH_MNEMONIC "fxch"
- #define X87_NOP_MNEMONIC "fnop"
- #define X87_FSTP1_MNEMONIC "fstp1"
- #define X87_FUCOMPP_MNEMONIC "fucompp"
- #define X87_DF_E0_TARGET "! ax"
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure provides basic information about an instruction, including
- its mnemonic name, operand encodings, and additional parsing information.
- Members:
- Mnemonic - Stores a pointer to the string containing the opcode's mnemonic.
- Target - Stores a pointer to a string describing the destination operand's
- encoding.
- Source - Stores a pointer to a string describing the source operand's
- encoding.
- Group - Stores the opcode group number. Some instructions require furthur
- decoding, the group number indicates that.
- --*/
- typedef struct _X86_INSTRUCTION_DEFINITION {
- PSTR Mnemonic;
- PSTR Target;
- PSTR Source;
- INT Group;
- } X86_INSTRUCTION_DEFINITION, *PX86_INSTRUCTION_DEFINITION;
- /*++
- Structure Description:
- This structure stores information about an instructions mnemonics and
- encoding when an array index is wasteful for describing the actual opcode
- number.
- Members:
- Prefix - Stores the specfic prefix value for which this instruction is
- valid.
- Opcode - Stores the opcode this definition defines.
- Instruction - Stores an array describing the mnemonics and encoding of the
- instruction.
- --*/
- typedef struct _X86_SPARSE_INSTRUCTION_DEFINITION {
- BYTE Prefix;
- BYTE Opcode;
- X86_INSTRUCTION_DEFINITION Instruction;
- } X86_SPARSE_INSTRUCTION_DEFINITION, *PX86_SPARSE_INSTRUCTION_DEFINITION;
- /*++
- Structure Description:
- This structure stores all binary information about a decoded instruction.
- Members:
- Prefix - Stores up to 4 prefix bytes, which is the maximum number of
- allowed prefixes in x86 instructions.
- Opcode - Stores the first (and many times only) opcode byte.
- Opcode2 - Stores the second opcode byte, if necessary (as determined by the
- first opcode byte).
- ModRm - Stores the ModR/M byte of the instruction, if one exists. Bits 6-7
- describe the Mod part of the instruction, which can describe what sort
- of addressing/displacement is encoded in the instruction. Bits 5-3 hold
- the Reg data, which stores either a register number or additional
- decoding information for instruction groups. Bits 2-0 store the R/M
- byte, which either stores another register value or describes how the
- memory information is encoded.
- Sib - Stores the Scale/Index/Base byte of the opcode, if one exists.
- Addressing with an sib byte usually looks like (Base + index * 2^Scale),
- where Base and Index are both general registers. Bits 6-7 describe the
- scale, which is raised to the power of two (and can therefore describe a
- scale of 1, 2, 4, or 8). Bits 5-3 describe the index register, and bits
- 2-0 describe the base register, both of which are encoded like the Reg
- field for general registers.
- Displacement - Stores the displacement of the instruction operand.
- Immediate - Stores the immediate value that may or may not be encoded in the
- instruction.
- Length - Stores the total size of this instruction encoding in bytes.
- DisplacementSize - Stores the size in bytes of the displacement value. Once
- the Displacement field is populated, this field is not too useful.
- ImmediateSize - Stores the size in bytes of the immediate value. Once the
- Immediate field is populated, this field is not too useful.
- OperandOverride - Stores a flag indicating whether or not the operand
- override prefix was on this instruction.
- AddressOverrride - Stores a flag indicating whether or not the address
- override prefix was specified on this instruction.
- Definition - Stores a the instruction decoding information,
- including the instruction mnemonic.
- --*/
- typedef struct _X86_INSTRUCTION {
- BYTE Prefix[X86_MAX_PREFIXES];
- BYTE Opcode;
- BYTE Opcode2;
- BYTE ModRm;
- BYTE Sib;
- ULONG Displacement;
- ULONG Immediate;
- ULONG Length;
- ULONG DisplacementSize;
- ULONG ImmediateSize;
- BOOL OperandOverride;
- BOOL AddressOverride;
- X86_INSTRUCTION_DEFINITION Definition;
- } X86_INSTRUCTION, *PX86_INSTRUCTION;
- typedef enum _X86_REGISTER_VALUE {
- X86RegisterValueEax,
- X86RegisterValueEcx,
- X86RegisterValueEdx,
- X86RegisterValueEbx,
- X86RegisterValueEsp,
- X86RegisterValueEbp,
- X86RegisterValueEsi,
- X86RegisterValueEdi,
- X86RegisterValueScaleIndexBase,
- X86RegisterValueDisplacement32,
- } X86_REGISTER_VALUE, *PX86_REGISTER_VALUE;
- typedef enum _X86_MOD_VALUE {
- X86ModValueNoDisplacement,
- X86ModValueDisplacement8,
- X86ModValueDisplacement32,
- X86ModValueRegister
- } X86_MOD_VALUE, *PX86_MOD_VALUE;
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Define working buffers. Note that this makes the disassembly code not thread
- // safe.
- //
- CHAR DbgX86DisassemblyBuffer[X86_WORKING_BUFFER_SIZE];
- CHAR DbgX86OperandBuffer[X86_WORKING_BUFFER_SIZE];
- //
- // Define the x86 instruction encodings.
- //
- X86_INSTRUCTION_DEFINITION DbgX86Instructions[256] = {
- {"add", "Eb", "Gb", 0}, /* 00 */
- {"add", "Ev", "Gv", 0}, /* 01 */
- {"add", "Gb", "Eb", 0}, /* 02 */
- {"add", "Gv", "Ev", 0}, /* 03 */
- {"add", "!bal", "Ib", 0}, /* 04 */
- {"add", "!rax", "Iz", 0}, /* 05 */
- {"push", "!wes", "", 0}, /* 06 */
- {"pop", "!wes", "", 0}, /* 07 */
- {"or", "Eb", "Gb", 0}, /* 08 */
- {"or", "Ev", "Gv", 0}, /* 09 */
- {"or", "Gb", "Eb", 0}, /* 0A */
- {"or", "Gv", "Ev", 0}, /* 0B */
- {"or", "!bal", "Ib", 0}, /* 0C */
- {"or", "!rax", "Iz", 0}, /* 0D */
- {"push", "!wcs", "", 0}, /* 0E */
- {"2BYTE", "", "", X86_INVALID_GROUP}, /* 0F */ /* Two Byte Opcodes */
- {"adc", "Eb", "Gb", 0}, /* 10 */
- {"adc", "Ev", "Gv", 0}, /* 11 */
- {"adc", "Gb", "Eb", 0}, /* 12 */
- {"adc", "Gv", "Ev", 0}, /* 13 */
- {"adc", "!bal", "Ib", 0}, /* 14 */
- {"adc", "!rax", "Iz", 0}, /* 15 */
- {"push", "!wss", "", 0}, /* 16 */
- {"pop", "!wss", "", 0}, /* 17 */
- {"sbb", "Eb", "Gb", 0}, /* 18 */
- {"sbb", "Ev", "Gv", 0}, /* 19 */
- {"sbb", "Gb", "Eb", 0}, /* 1A */
- {"sbb", "Gv", "Ev", 0}, /* 1B */
- {"sbb", "!bal", "Ib", 0}, /* 1C */
- {"sbb", "!rax", "Iz", 0}, /* 1D */
- {"push", "!wds", "", 0}, /* 1E */
- {"pop", "!wds", "", 0}, /* 1F */
- {"and", "Eb", "Gb", 0}, /* 20 */
- {"and", "Ev", "Gv", 0}, /* 21 */
- {"and", "Gb", "Eb", 0}, /* 22 */
- {"and", "Gv", "Ev", 0}, /* 23 */
- {"and", "!bal", "Ib", 0}, /* 24 */
- {"and", "!rax", "Iz", 0}, /* 25 */
- {"ES:", "", "", X86_INVALID_GROUP}, /* 26 */ /* ES prefix */
- {"daa", "", "", 0}, /* 27 */
- {"sub", "Eb", "Gb", 0}, /* 28 */
- {"sub", "Ev", "Gv", 0}, /* 29 */
- {"sub", "Gb", "Eb", 0}, /* 2A */
- {"sub", "Gv", "Ev", 0}, /* 2B */
- {"sub", "!bal", "Ib", 0}, /* 2C */
- {"sub", "!rax", "Iz", 0}, /* 2D */
- {"CS:", "", "", X86_INVALID_GROUP}, /* 2E */ /* CS prefix */
- {"das", "", "", 0}, /* 2F */
- {"xor", "Eb", "Gb", 0}, /* 30 */
- {"xor", "Ev", "Gv", 0}, /* 31 */
- {"xor", "Gb", "Eb", 0}, /* 32 */
- {"xor", "Gv", "Ev", 0}, /* 33 */
- {"xor", "!bal", "Ib", 0}, /* 34 */
- {"xor", "!rax", "Iz", 0}, /* 35 */
- {"SS:", "", "", X86_INVALID_GROUP}, /* 36 */ /* SS prefix */
- {"aaa", "", "", 0}, /* 37 */
- {"cmp", "Eb", "Gb", 0}, /* 38 */
- {"cmp", "Ev", "Gv", 0}, /* 39 */
- {"cmp", "Gb", "Eb", 0}, /* 3A */
- {"cmp", "Gv", "Ev", 0}, /* 3B */
- {"cmp", "!bal", "Ib", 0}, /* 3C */
- {"cmp", "!rax", "Iz", 0}, /* 3D */
- {"DS:", "", "", X86_INVALID_GROUP}, /* 3E */ /* DS prefix */
- {"aas", "", "", 0}, /* 3F */
- {"inc", "!eax", "", 0}, /* 40 */
- {"inc", "!ecx", "", 0}, /* 41 */
- {"inc", "!edx", "", 0}, /* 42 */
- {"inc", "!ebx", "", 0}, /* 43 */
- {"inc", "!esp", "", 0}, /* 44 */
- {"inc", "!ebp", "", 0}, /* 45 */
- {"inc", "!esi", "", 0}, /* 46 */
- {"inc", "!edi", "", 0}, /* 47 */
- {"dec", "!eax", "", 0}, /* 48 */
- {"dec", "!ecx", "", 0}, /* 49 */
- {"dec", "!edx", "", 0}, /* 4A */
- {"dec", "!ebx", "", 0}, /* 4B */
- {"dec", "!esp", "", 0}, /* 4C */
- {"dec", "!ebp", "", 0}, /* 4D */
- {"dec", "!esi", "", 0}, /* 4E */
- {"dec", "!edi", "", 0}, /* 4F */
- {"push", "!rax", "", 0}, /* 50 */
- {"push", "!rcx", "", 0}, /* 51 */
- {"push", "!rdx", "", 0}, /* 52 */
- {"push", "!rbx", "", 0}, /* 53 */
- {"push", "!rsp", "", 0}, /* 54 */
- {"push", "!rbp", "", 0}, /* 55 */
- {"push", "!rsi", "", 0}, /* 56 */
- {"push", "!rdi", "", 0}, /* 57 */
- {"pop", "!rax", "", 0}, /* 58 */
- {"pop", "!rcx", "", 0}, /* 59 */
- {"pop", "!rdx", "", 0}, /* 5A */
- {"pop", "!rbx", "", 0}, /* 5B */
- {"pop", "!rsp", "", 0}, /* 5C */
- {"pop", "!rbp", "", 0}, /* 5D */
- {"pop", "!rsi", "", 0}, /* 5E */
- {"pop", "!rdi", "", 0}, /* 5F */
- {"pushad", "", "", 0}, /* 60 */
- {"popad", "", "", 0}, /* 61 */
- {"bound", "Gv", "Ma", 0}, /* 62 */
- {"arpl", "Ew", "Gw", 0}, /* 63 */
- {"FS:", "", "", X86_INVALID_GROUP}, /* 64 */ /* FS prefix */
- {"GS:", "", "", X86_INVALID_GROUP}, /* 65 */ /* GS prefix */
- {"OPSIZE:", "", "", X86_INVALID_GROUP}, /* 66 */ /* Operand override */
- {"ADSIZE:", "", "", X86_INVALID_GROUP}, /* 67 */ /* Address override */
- {"push", "Iz", "", 0}, /* 68 */
- {"imul", "Gv", "Ev", 0}, /* 69 */ /* Also has Iz */
- {"push", "Ib", "", 0}, /* 6A */
- {"imul", "Gv", "Ev", 0}, /* 6B */ /* Also has Ib */
- {"ins", "Yb", "!wdx", 0}, /* 6C */
- {"ins", "Yz", "!wdx", 0}, /* 6D */
- {"outs", "!wdx", "Xb", 0}, /* 6E */
- {"outs", "!wdx", "Xz", 0}, /* 6F */
- {"jo ", "Jb", "", 0}, /* 70 */
- {"jno", "Jb", "", 0}, /* 71 */
- {"jb ", "Jb", "", 0}, /* 72 */
- {"jnb", "Jb", "", 0}, /* 73 */
- {"jz ", "Jb", "", 0}, /* 74 */
- {"jnz", "Jb", "", 0}, /* 75 */
- {"jbe", "Jb", "", 0}, /* 76 */
- {"jnbe", "Jb", "", 0}, /* 77 */
- {"js ", "Jb", "", 0}, /* 78 */
- {"jns", "Jb", "", 0}, /* 79 */
- {"jp ", "Jb", "", 0}, /* 7A */
- {"jnp", "Jb", "", 0}, /* 7B */
- {"jl ", "Jb", "", 0}, /* 7C */
- {"jnl", "Jb", "", 0}, /* 7D */
- {"jle", "Jb", "", 0}, /* 7E */
- {"jnle", "Jb", "", 0}, /* 7F */
- {"GRP1", "Eb", "Ib", 1}, /* 80 */ /* Group 1 opcodes. */
- {"GRP1", "Ev", "Iz", 1}, /* 81 */ /* Reg of ModR/M */
- {"GRP1", "Eb", "Ib", 1}, /* 82 */ /* extends opcode.*/
- {"GRP1", "Ev", "Ib", 1}, /* 83 */
- {"test", "Eb", "Gb", 0}, /* 84 */
- {"test", "Ev", "Gv", 0}, /* 85 */
- {"xchg", "Eb", "Eb", 0}, /* 86 */
- {"xchg", "Ev", "Gv", 0}, /* 87 */
- {"mov", "Eb", "Gb", 0}, /* 88 */
- {"mov", "Ev", "Gv", 0}, /* 89 */
- {"mov", "Gb", "Eb", 0}, /* 8A */
- {"mov", "Gv", "Ev", 0}, /* 8B */
- {"mov", "Ev", "Sw", 0}, /* 8C */
- {"lea", "Gv", "Ml", 0}, /* 8D */
- {"mov", "Sw", "Ev", 0}, /* 8E */
- {"pop", "Ev", "", 10}, /* 8F */ /* Group 10 */
- {"nop", "", "", 0}, /* 90 */ /* nop */
- {"xchg", "!rcx", "!rax", 0}, /* 91 */
- {"xchg", "!rdx", "!rax", 0}, /* 92 */
- {"xchg", "!rbx", "!rax", 0}, /* 93 */
- {"xchg", "!rsp", "!rax", 0}, /* 94 */
- {"xchg", "!rbp", "!rax", 0}, /* 95 */
- {"xchg", "!rsi", "!rax", 0}, /* 96 */
- {"xchg", "!rdi", "!rax", 0}, /* 97 */
- {"cwde", "", "", 0}, /* 98 */
- {"cdq", "", "", 0}, /* 99 */
- {"call", "Ap", "", 0}, /* 9A */
- {"fwait", "", "", 0}, /* 9B */
- {"pushf", "", "", 0}, /* 9C */ /* arg1 = Fv */
- {"popf", "", "", 0}, /* 9D */ /* arg1 = Fv */
- {"sahf", "", "", 0}, /* 9E */
- {"lafh", "", "", 0}, /* 9F */
- {"mov", "!bal", "Ob", 0}, /* A0 */
- {"mov", "!rax", "Ov", 0}, /* A1 */
- {"mov", "Ob", "!bal", 0}, /* A2 */
- {"mov", "Ov", "!rax", 0}, /* A3 */
- {"movs", "Yb", "Xb", 0}, /* A4 */
- {"movs", "Yv", "Xv", 0}, /* A5 */
- {"cmps", "Yb", "Xb", 0}, /* A6 */
- {"cmps", "Yv", "Xv", 0}, /* A7 */
- {"test", "!bal", "Ib", 0}, /* A8 */
- {"test", "!rax", "Iz", 0}, /* A9 */
- {"stos", "Yb", "!bal", 0}, /* AA */
- {"stos", "Yv", "!rax", 0}, /* AB */
- {"lods", "!bal", "Xb", 0}, /* AC */
- {"lods", "!rax", "Xv", 0}, /* AD */
- {"scas", "Yb", "!bal", 0}, /* AE */
- {"scas", "Yv", "!rax", 0}, /* AF */
- {"mov", "!bal", "Ib", 0}, /* B0 */
- {"mov", "!bcl", "Ib", 0}, /* B1 */
- {"mov", "!bdl", "Ib", 0}, /* B2 */
- {"mov", "!bbl", "Ib", 0}, /* B3 */
- {"mov", "!bah", "Ib", 0}, /* B4 */
- {"mov", "!bch", "Ib", 0}, /* B5 */
- {"mov", "!bdh", "Ib", 0}, /* B6 */
- {"mov", "!bbh", "Ib", 0}, /* B7 */
- {"mov", "!rax", "Iv", 0}, /* B8 */
- {"mov", "!rcx", "Iv", 0}, /* B9 */
- {"mov", "!rdx", "Iv", 0}, /* BA */
- {"mov", "!rbx", "Iv", 0}, /* BB */
- {"mov", "!rsp", "Iv", 0}, /* BC */
- {"mov", "!rbp", "Iv", 0}, /* BD */
- {"mov", "!rsi", "Iv", 0}, /* BE */
- {"mov", "!rdi", "Iv", 0}, /* BF */
- {"GRP2", "Eb", "Ib", 2}, /* C0 */ /* Group 2 */
- {"GRP2", "Ev", "Ib", 2}, /* C1 */ /* Group 2 */
- {"ret", "Iw", "", 0}, /* C2 */
- {"ret", "", "", 0}, /* C3 */
- {"les", "Gz", "Mp", 0}, /* C4 */
- {"lds", "Gz", "Mp", 0}, /* C5 */
- {"mov", "Eb", "Ib", 12}, /* C6 */ /* Group 12 */
- {"mov", "Ev", "Iz", 12}, /* C7 */ /* Group 12 */
- {"enter", "Iw", "Ib", 0}, /* C8 */
- {"leave", "", "", 0}, /* C9 */
- {"retf", "Iw", "", 0}, /* CA */
- {"retf", "", "", 0}, /* CB */
- {"int", "!b3", "", 0}, /* CC */ /* Int 3 */
- {"int", "Ib", "", 0}, /* CD */
- {"into", "", "", 0}, /* CE */
- {"iret", "", "", 0}, /* CF */
- {"GRP2", "Eb", "!b1", 2}, /* D0 */ /* Group 2, arg2 = 1 */
- {"GRP2", "Ev", "!b1", 2}, /* D1 */ /* Group 2, arg2 = 1 */
- {"GRP2", "Eb", "!bcl", 2}, /* D2 */ /* Group 2 */
- {"GRP2", "Ev", "!bcl", 2}, /* D3 */ /* Group 2 */
- {"aam", "Ib", "", 0}, /* D4 */
- {"aad", "Ib", "", 0}, /* D5 */
- {"setalc", "", "", 0}, /* D6 */
- {"xlat", "", "", 0}, /* D7 */
- {"ESC0", "Ev", "", 0x87}, /* D8 */ /* x87 Floating Pt */
- {"ESC1", "Ev", "", 0x87}, /* D9 */
- {"ESC2", "Ev", "", 0x87}, /* DA */
- {"ESC3", "Ev", "", 0x87}, /* DB */
- {"ESC4", "Ev", "", 0x87}, /* DC */
- {"ESC5", "Ev", "", 0x87}, /* DD */
- {"ESC6", "Ev", "", 0x87}, /* DE */
- {"ESC7", "Ev", "", 0x87}, /* DF */
- {"loopnz", "Jb", "", 0}, /* E0 */
- {"loopz", "Jb", "", 0}, /* E1 */
- {"loop", "Jb", "", 0}, /* E2 */
- {"jecx", "Jb", "", 0}, /* E3 */
- {"in ", "!bal", "Ib", 0}, /* E4 */
- {"in ", "!eax", "Iv", 0}, /* E5 */
- {"out", "Ib", "!bal", 0}, /* E6 */
- {"out", "Ib", "!eax", 0}, /* E7 */
- {"call", "Jz", "", 0}, /* E8 */
- {"jmp", "Jz", "", 0}, /* E9 */
- {"jmp", "Ap", "", 0}, /* EA */
- {"jmp", "Jb", "", 0}, /* EB */
- {"in ", "!bal", "!wdx", 0}, /* EC */
- {"in ", "!eax", "!wdx", 0}, /* ED */
- {"out", "!wdx", "!bal", 0}, /* EE */
- {"out", "!wdx", "!eax", 0}, /* EF */
- {"LOCK:", "", "", 0}, /* F0 */ /* Lock prefix */
- {"int", "!b1", "", 0}, /* F1 */ /* Int 1 */
- {"REPNE:", "", "", 0}, /* F2 */ /* Repne prefix */
- {"REP:", "", "", 0}, /* F3 */ /* Rep prefix */
- {"hlt", "", "", 0}, /* F4 */
- {"cmc", "", "", 0}, /* F5 */
- {"GRP3", "Eb", "", 3}, /* F6 */ /* Group 3 */
- {"GRP3", "Ev", "", 0x3A}, /* F7 */ /* Group 3A */
- {"clc", "", "", 0}, /* F8 */
- {"stc", "", "", 0}, /* F9 */
- {"cli", "", "", 0}, /* FA */
- {"sti", "", "", 0}, /* FB */
- {"cld", "", "", 0}, /* FC */
- {"std", "", "", 0}, /* FD */
- {"GRP4", "Eb", "", 4}, /* FE */ /* Group 4 */
- {"GRP5", "Ev", "", 5}, /* FF */ /* Group 5 */
- };
- X86_SPARSE_INSTRUCTION_DEFINITION DbgX86TwoByteInstructions[] = {
- {0, 0x0, {"GRP6", "", "", 6}}, /* 00 */ /* Group 6 */
- {0, 0x1, {"GRP7", "", "", 7}}, /* 01 */ /* Group 7 */
- {0, 0x2, {"lar", "Gv", "Ew", 0}}, /* 02 */
- {0, 0x3, {"lsl", "Gv", "Ew", 0}}, /* 03 */
- {0, 0x5, {"loadall/syscall", "", "", 0}}, /* 05 */
- {0, 0x6, {"clts", "", "", 0}}, /* 06 */
- {0, 0x7, {"loadall/sysret", "", "", 0}}, /* 07 */
- {0, 0x8, {"invd", "", "", 0}}, /* 08 */
- {0, 0x9, {"wbinvd", "", "", 0}}, /* 09 */
- {0, 0xB, {"ud1", "", "", 0}}, /* 0B */
- {0, 0x10, {"umov", "Eb", "Gb", 0}}, /* 10 */
- {0, 0x11, {"umov", "Ev", "Gv", 0}}, /* 11 */
- {0, 0x12, {"umov", "Gb", "Eb", 0}}, /* 12 */
- {0, 0x13, {"umov", "Gv", "Ev", 0}}, /* 13 */
- {0, 0x20, {"mov", "Rd", "Cd", 0}}, /* 20 */
- {0, 0x21, {"mov", "Rd", "Dd", 0}}, /* 21 */
- {0, 0x22, {"mov", "Cd", "Rd", 0}}, /* 22 */
- {0, 0x23, {"mov", "Dd", "Rd", 0}}, /* 23 */
- {0, 0x30, {"wrmsr", "", "", 0}}, /* 30 */
- {0, 0x31, {"rdtsc", "", "", 0}}, /* 31 */
- {0, 0x32, {"rdmsr", "", "", 0}}, /* 32 */
- {0, 0x33, {"rdpmc", "", "", 0}}, /* 33 */
- {0, 0x34, {"sysenter", "", "", 0}}, /* 34 */
- {0, 0x35, {"sysexit", "", "", 0}}, /* 35 */
- {0, 0x37, {"getsec", "", "", 0}}, /* 37 */
- {0, 0x40, {"cmovo", "Gv", "Ev", 0}}, /* 40 */
- {0, 0x41, {"cmovno", "Gv", "Ev", 0}}, /* 41 */
- {0, 0x42, {"cmovb", "Gv", "Ev", 0}}, /* 42 */
- {0, 0x43, {"cmovnb", "Gv", "Ev", 0}}, /* 43 */
- {0, 0x44, {"cmovz", "Gv", "Ev", 0}}, /* 44 */
- {0, 0x45, {"cmovnz", "Gv", "Ev", 0}}, /* 45 */
- {0, 0x46, {"cmovbe", "Gv", "Ev", 0}}, /* 46 */
- {0, 0x47, {"cmovnbe", "Gv", "Ev", 0}}, /* 47 */
- {0, 0x48, {"cmovs", "Gv", "Ev", 0}}, /* 48 */
- {0, 0x49, {"cmovns", "Gv", "Ev", 0}}, /* 49 */
- {0, 0x4A, {"cmovp", "Gv", "Ev", 0}}, /* 4A */
- {0, 0x4B, {"cmovnp", "Gv", "Ev", 0}}, /* 4B */
- {0, 0x4C, {"cmovl", "Gv", "Ev", 0}}, /* 4C */
- {0, 0x4D, {"cmovnl", "Gv", "Ev", 0}}, /* 4D */
- {0, 0x4E, {"cmovle", "Gv", "Ev", 0}}, /* 4E */
- {0, 0x4F, {"cmovnle", "Gv", "Ev", 0}}, /* 4F */
- {0, 0x80, {"jo ", "Jz", "", 0}}, /* 80 */
- {0, 0x81, {"jno", "Jz", "", 0}}, /* 81 */
- {0, 0x82, {"jb ", "Jz", "", 0}}, /* 82 */
- {0, 0x83, {"jnb", "Jz", "", 0}}, /* 83 */
- {0, 0x84, {"jz ", "Jz", "", 0}}, /* 84 */
- {0, 0x85, {"jnz", "Jz", "", 0}}, /* 85 */
- {0, 0x86, {"jbe", "Jz", "", 0}}, /* 86 */
- {0, 0x87, {"jnbe", "Jz", "", 0}}, /* 87 */
- {0, 0x88, {"js ", "Jz", "", 0}}, /* 88 */
- {0, 0x89, {"jns", "Jz", "", 0}}, /* 89 */
- {0, 0x8A, {"jp", "Jz", "", 0}}, /* 8A */
- {0, 0x8B, {"jnp", "Jz", "", 0}}, /* 8B */
- {0, 0x8C, {"jl ", "Jz", "", 0}}, /* 8C */
- {0, 0x8D, {"jnl", "Jz", "", 0}}, /* 8D */
- {0, 0x8E, {"jle", "Jz", "", 0}}, /* 8E */
- {0, 0x8F, {"jnle", "Jz", "", 0}}, /* 8F */
- {0, 0x90, {"seto", "Eb", "", 0}}, /* 90 */
- {0, 0x91, {"setno", "Eb", "", 0}}, /* 91 */
- {0, 0x92, {"setb", "Eb", "", 0}}, /* 92 */
- {0, 0x93, {"setnb", "Eb", "", 0}}, /* 93 */
- {0, 0x94, {"setz", "Eb", "", 0}}, /* 94 */
- {0, 0x95, {"setnz", "Eb", "", 0}}, /* 95 */
- {0, 0x96, {"setbe", "Eb", "", 0}}, /* 96 */
- {0, 0x97, {"setnbe", "Eb", "", 0}}, /* 97 */
- {0, 0x98, {"sets", "Eb", "", 0}}, /* 98 */
- {0, 0x99, {"setns", "Eb", "", 0}}, /* 99 */
- {0, 0x9A, {"setp", "Eb", "", 0}}, /* 9A */
- {0, 0x9B, {"setnp", "Eb", "", 0}}, /* 9B */
- {0, 0x9C, {"setl", "Eb", "", 0}}, /* 9C */
- {0, 0x9D, {"setnl", "Eb", "", 0}}, /* 9D */
- {0, 0x9E, {"setle", "Eb", "", 0}}, /* 9E */
- {0, 0x9F, {"setnle", "Eb", "", 0}}, /* 9F */
- {0, 0xA0, {"push", "!wfs", "", 0}}, /* A0 */
- {0, 0xA1, {"pop", "!wfs", "", 0}}, /* A1 */
- {0, 0xA2, {"cpuid", "", "", 0}}, /* A2 */
- {0, 0xA3, {"bt ", "Ev", "Gv", 0}}, /* A3 */
- {0, 0xA4, {"shld", "Ev", "Gv", 0}}, /* A4 */ /* also has Ib */
- {0, 0xA5, {"shld", "Ev", "Gv", 0}}, /* A5 */ /* also has !bcl */
- {0, 0xA6, {"cmpxchg", "", "", 0}}, /* A6 */
- {0, 0xA7, {"cmpxchg", "", "", 0}}, /* A7 */
- {0, 0xA8, {"push", "!wgs", "", 0}}, /* A8 */
- {0, 0xA9, {"pop", "!gs", "", 0}}, /* A9 */
- {0, 0xAA, {"rsm", "", "", 0}}, /* AA */
- {0, 0xAB, {"bts", "Ev", "Gv", 0}}, /* AB */
- {0, 0xAC, {"shrd", "Ev", "Gv", 0}}, /* AC */ /* Also has Ib */
- {0, 0xAD, {"shrd", "Ev", "Gv", 0}}, /* AD */ /* Also has !bcl */
- {0, 0xAE, {"GRP15", "", "", 15}}, /* AE */ /* Group 15 */
- {0, 0xAF, {"imul", "Gv", "Ev", 0}}, /* AF */
- {0, 0xB0, {"cmpxchg", "Eb", "Gb", 0}}, /* B0 */
- {0, 0xB1, {"cmpxchg", "Ev", "Gv", 0}}, /* B1 */
- {0, 0xB2, {"lss", "Gz", "Mp", 0}}, /* B2 */
- {0, 0xB3, {"btr", "Ev", "Gv", 0}}, /* B3 */
- {0, 0xB4, {"lfs", "Gz", "Mp", 0}}, /* B4 */
- {0, 0xB5, {"lgs", "Gz", "Mp", 0}}, /* B5 */
- {0, 0xB6, {"movzx", "Gv", "Eb", 0}}, /* B6 */
- {0, 0xB7, {"movxz", "Gv", "Ew", 0}}, /* B7 */
- {0, 0xB8, {"jmpe", "Jz", "", 0}}, /* B8 */
- {0, 0xB9, {"ud2", "", "", 11}}, /* B9 */ /* Group 11 */
- {0, 0xBA, {"GRP8", "Ev", "Ib", 8}}, /* BA */ /* Group 8 */
- {0, 0xBB, {"btc", "Ev", "Gv", 0}}, /* BB */
- {0, 0xBC, {"bsf", "Gv", "Ev", 0}}, /* BC */
- {0, 0xBD, {"bsr", "Gv", "Ev", 0}}, /* BD */
- {0, 0xBE, {"movsx", "Gv", "Eb", 0}}, /* BE */
- {0, 0xBF, {"movsx", "Gv", "Ew", 0}}, /* BF */
- {0xF3, 0xB8, {"popcnt", "Gv", "Ev", 0}}, /* B8 */
- {0xF3, 0xBD, {"lzcnt", "Gv", "Ev", 0}}, /* BD */
- {0, 0xC0, {"xadd", "Eb", "Gb", 0}}, /* C0 */
- {0, 0xC1, {"xadd", "Ev", "Gv", 0}}, /* C1 */
- {0, 0xC7, {"GRP9", "", "", 9}}, /* C7 */ /* Group 9 */
- {0, 0xC8, {"bswap", "!leax", "", 0}}, /* C8 */
- {0, 0xC9, {"bswap", "!lecx", "", 0}}, /* C9 */
- {0, 0xCA, {"bswap", "!ledx", "", 0}}, /* CA */
- {0, 0xCB, {"bswap", "!lebx", "", 0}}, /* CB */
- {0, 0xCC, {"bswap", "!lesp", "", 0}}, /* CC */
- {0, 0xCD, {"bswap", "!lebp", "", 0}}, /* CD */
- {0, 0xCE, {"bswap", "!lesi", "", 0}}, /* CE */
- {0, 0xCF, {"bswap", "!ledi", "", 0}}, /* CF */
- {0, 0xFF, {"ud", "", "", 0}}, /* FF */
- {0x66, 0xFF, {"ud", "", "", 0}}, /* FF */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- {0, 0x0, {"", "", "", 0}}, /* 00 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group1Instructions[8] = {
- {"add", "", "", 0}, /* 00 */
- {"or ", "", "", 0}, /* 01 */
- {"adc", "", "", 0}, /* 02 */
- {"sbb", "", "", 0}, /* 03 */
- {"and", "", "", 0}, /* 04 */
- {"sub", "", "", 0}, /* 05 */
- {"xor", "", "", 0}, /* 06 */
- {"cmp", "", "", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group2Instructions[8] = {
- {"rol", "", "", 0}, /* 00 */
- {"ror", "", "", 0}, /* 01 */
- {"rcl", "", "", 0}, /* 02 */
- {"rcr", "", "", 0}, /* 03 */
- {"shl", "", "", 0}, /* 04 */
- {"shr", "", "", 0}, /* 05 */
- {"sal", "", "", 0}, /* 06 */
- {"sar", "", "", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group3Instructions[8] = {
- {"test", "Ev", "Ib", 0}, /* 00 */
- {"test", "Ev", "Ib", 0}, /* 01 */
- {"not", "", "", 0}, /* 02 */
- {"neg", "", "", 0}, /* 03 */
- {"mul", "", "!rax", 0}, /* 04 */
- {"mul", "", "!rax", 0}, /* 05 */
- {"div", "", "!rax", 0}, /* 06 */
- {"div", "", "!rax", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group3AInstructions[8] = {
- {"test", "Ev", "Iz", 0}, /* 00 */
- {"test", "Ev", "Iz", 0}, /* 01 */
- {"not", "", "", 0}, /* 02 */
- {"neg", "", "", 0}, /* 03 */
- {"mul", "", "!rax", 0}, /* 04 */
- {"mul", "", "!rax", 0}, /* 05 */
- {"div", "", "!rax", 0}, /* 06 */
- {"div", "", "!rax", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION
- DbgX86Group4Instructions[X86_GROUP_4_INSTRUCTION_COUNT] = {
- {"inc", "Eb", "", 0}, /* 00 */
- {"dec", "Eb", "", 0}, /* 01 */
- };
- X86_INSTRUCTION_DEFINITION
- DbgX86Group5Instructions[X86_GROUP_5_INSTRUCTION_COUNT] = {
- {"inc", "Ev", "", 0}, /* 00 */
- {"dec", "Ev", "", 0}, /* 01 */
- {"call", "Ev", "", 0}, /* 02 */
- {"call", "Mp", "", 0}, /* 03 */
- {"jmp", "Ev", "", 0}, /* 04 */
- {"jmp", "Mp", "", 0}, /* 05 */
- {"push", "Ev", "", 0}, /* 06 */
- };
- X86_INSTRUCTION_DEFINITION
- DbgX86Group6Instructions[X86_GROUP_6_INSTRUCTION_COUNT] = {
- {"sldt", "Ev", "", 0}, /* 00 */
- {"str", "Ev", "", 0}, /* 01 */
- {"lldt", "Ev", "", 0}, /* 02 */
- {"ltr", "Ev", "", 0}, /* 03 */
- {"verr", "Ev", "", 0}, /* 04 */
- {"verw", "Ev", 0}, /* 05 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group7Instructions[8] = {
- {"sgdt", "Ms", "", 0}, /* 00 */
- {"sidt", "Ms", "", 0}, /* 01 */
- {"lgdt", "Ms", "", 0}, /* 02 */
- {"lidt", "Ms", "", 0}, /* 03 */
- {"smsw", "Mw", "", 0}, /* 04 */
- {"", "", "", X86_INVALID_GROUP}, /* 05 */
- {"lmsw", "Mw", "", 0}, /* 06 */
- {"invlpg", "Ml", "", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group8Instructions[8] = {
- {"", "", "", X86_INVALID_GROUP}, /* 00 */
- {"", "", "", X86_INVALID_GROUP}, /* 01 */
- {"", "", "", X86_INVALID_GROUP}, /* 02 */
- {"", "", "", X86_INVALID_GROUP}, /* 03 */
- {"bt ", "", "", 0}, /* 04 */
- {"bts", "", 0}, /* 05 */
- {"btr", "", "", 0}, /* 06 */
- {"btc", "", "", 0}, /* 07 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group9Instructions[8] = {
- {"", "", "", X86_INVALID_GROUP}, /* 00 */
- {"cmpxchg", "Mq", "", 0}, /* 01 */
- };
- X86_INSTRUCTION_DEFINITION DbgX86Group15Instructions[8] = {
- {"fxsave", "M", "", 0}, /* 00 */
- {"fxrstor", "M", "", 0}, /* 01 */
- {"vldmxcsr", "Md", "", 0}, /* 02 */
- {"vstmxcsr", "Md", "", 0}, /* 03 */
- {"xsave", "M", "", 0}, /* 04 */
- {"xrstor", "M", "", 0}, /* 05 */
- {"xsaveopt", "M", "", 0}, /* 06 */
- {"clflush", "M", "", 0}, /* 07 */
- };
- X86_SPARSE_INSTRUCTION_DEFINITION DbgX860F01Alternates[] = {
- {0, 0xC1, {"vmcall", "", "", 0}},
- {0, 0xC2, {"vmlaunch", "", "", 0}},
- {0, 0xC3, {"vmresume", "", "", 0}},
- {0, 0xC4, {"vmxoff", "", "", 0}},
- {0, 0xC8, {"monitor", "", "", 0}},
- {0, 0xC9, {"mwait", "", "", 0}},
- {0, 0xCA, {"clac", "", "", 0}},
- {0, 0xCB, {"stac", "", "", 0}},
- {0, 0xCF, {"encls", "", "", 0}},
- {0, 0xD0, {"xgetbv", "", "", 0}},
- {0, 0xD1, {"xsetbv", "", "", 0}},
- {0, 0xD4, {"vmfunc", "", "", 0}},
- {0, 0xD5, {"xend", "", "", 0}},
- {0, 0xD6, {"xtest", "", "", 0}},
- {0, 0xD7, {"enclu", "", "", 0}},
- {0, 0xD8, {"vmrun", "", "", 0}},
- {0, 0xD9, {"vmmcall", "", "", 0}},
- {0, 0xDA, {"vmload", "", "", 0}},
- {0, 0xDB, {"vmsave", "", "", 0}},
- {0, 0xDC, {"stgi", "", "", 0}},
- {0, 0xDD, {"clgi", "", "", 0}},
- {0, 0xDE, {"skinit", "", "", 0}},
- {0, 0xDF, {"invlpga", "", "", 0}},
- {0, 0xEE, {"rdpkru", "", "", 0}},
- {0, 0xEF, {"wrpkru", "", "", 0}},
- {0, 0xF8, {"swapgs", "", "", 0}},
- {0, 0xF9, {"rdtscp", "", "", 0}},
- {0, 0xFA, {"monitorx", "", "", 0}},
- {0, 0xFB, {"mwaitx", "", "", 0}},
- {0, 0xFC, {"clzero", "", "", 0}},
- };
- //
- // Define the various x87 floating point mnemonics. The first index is the
- // first opcode (offset from 0xD8), and the second index is the reg2 portion
- // of the ModR/M byte. These are only valid if the mod portion of ModR/M
- // does not specify a register. If it specifies a register, then there are
- // different arrays used for decoding.
- //
- PSTR DbgX87Instructions[8][8] = {
- {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsub",
- "fsubr",
- "fdiv",
- "fdivr"
- },
- {
- "fld",
- NULL,
- "fst",
- "fstp",
- "fldenv",
- "fldcw",
- "fstenv",
- "fstcw"
- },
- {
- "fiadd",
- "fimul",
- "ficom",
- "ficomp",
- "fisub",
- "fisubr",
- "fidiv",
- "fidivr"
- },
- {
- "fild",
- "fisttp",
- "fist",
- "fistp",
- NULL,
- "fld",
- NULL,
- "fstp"
- },
- {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsub",
- "fsubr",
- "fdiv",
- "fdivr"
- },
- {
- "fld",
- "fisttp",
- "fst",
- "fstp",
- "frstor",
- NULL,
- "fsave",
- "fstsw"
- },
- {
- "fiadd",
- "fimul",
- "ficom",
- "ficomp",
- "fisub",
- "fisubr",
- "fidiv",
- "fidivr"
- },
- {
- "fild",
- "fisttp",
- "fist",
- "fistp",
- "fbld",
- "fild",
- "fbstp",
- "fistp"
- }
- };
- PSTR DbgX87D9E0Instructions[32] = {
- "fchs",
- "fabs",
- NULL,
- NULL,
- "ftst",
- "fxam",
- "ftstp",
- NULL,
- "fld1",
- "fldl2t",
- "fldl2e",
- "fldpi",
- "fldlg2",
- "fldln2",
- "fldz",
- NULL,
- "f2xm1",
- "fyl2x",
- "fptan",
- "fpatan",
- "fxtract",
- "fprem1",
- "fdecstp",
- "fincstp",
- "fprem",
- "fyl2xp1",
- "fsqrt",
- "fsincos",
- "frndint",
- "fscale",
- "fsin",
- "fcos",
- };
- PSTR DbgX87DAC0Instructions[8] = {
- "fcmovb",
- "fcmove",
- "fcmovbe",
- "fcmovu",
- NULL,
- NULL,
- NULL,
- NULL
- };
- PSTR DbgX87DBC0Instructions[8] = {
- "fcmovnb",
- "fcmovne",
- "fcmovnbe",
- "fcmovnu",
- NULL,
- "fucomi",
- "fcomi",
- NULL
- };
- PSTR DbgX87DBE0Instructions[8] = {
- "feni",
- "fdisi",
- "fclex",
- "finit",
- "fsetpm",
- "frstpm",
- NULL,
- NULL
- };
- PSTR DbgX87DCC0Instructions[8] = {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsubr",
- "fsub",
- "fdivr",
- "fdiv",
- };
- PSTR DbgX87DDC0Instructions[8] = {
- "ffree",
- "fxch",
- "fst",
- "fstp",
- "fucom",
- "fucomp",
- NULL,
- NULL,
- };
- PSTR DbgX87DEC0Instructions[8] = {
- "faddp",
- "fmulp",
- "fcomp",
- NULL,
- "fsubrp",
- "fsubp",
- "fdivrp",
- "fdivp",
- };
- PSTR DbgX87DFC0Instructions[8] = {
- "freep",
- "fxch",
- "fstp",
- "fstp",
- NULL,
- "fucomip",
- "fcomip",
- NULL,
- };
- PSTR DbgX87DFE0Instructions[X87_DF_E0_COUNT] = {
- "fstsw",
- "fstdw",
- "fstsg",
- };
- //
- // Define the register name constants.
- //
- PSTR DbgX86DebugRegisterNames[X86_DEBUG_REGISTER_COUNT] = {
- "dr0",
- "dr1",
- "dr2",
- "dr3",
- "dr4",
- "dr5",
- "dr6",
- "dr7"
- };
- PSTR DbgX86SegmentRegisterNames[X86_SEGMENT_REGISTER_COUNT] = {
- "es",
- "cs",
- "ss",
- "ds",
- "fs",
- "gs"
- };
- PSTR DbgX86RegisterNames8Bit[X86_REGISTER_NAME_COUNT] = {
- "al",
- "cl",
- "dl",
- "bl",
- "ah",
- "ch",
- "dh",
- "bh",
- };
- PSTR DbgX86RegisterNames16Bit[X86_REGISTER_NAME_COUNT] = {
- "ax",
- "cx",
- "dx",
- "bx",
- "sp",
- "bp",
- "si",
- "di"
- };
- PSTR DbgX86RegisterNames32Bit[X86_REGISTER_NAME_COUNT] = {
- "eax",
- "ecx",
- "edx",
- "ebx",
- "esp",
- "ebp",
- "esi",
- "edi"
- };
- PSTR DbgX87RegisterNames[X86_REGISTER_NAME_COUNT] = {
- "st(0)",
- "st(1)",
- "st(2)",
- "st(3)",
- "st(4)",
- "st(5)",
- "st(6)",
- "st(7)",
- };
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- BOOL
- DbgpX86PrintOperand (
- ULONGLONG InstructionPointer,
- PX86_INSTRUCTION Instruction,
- PSTR OperandFormat,
- PSTR Operand,
- ULONG BufferLength,
- PULONGLONG Address,
- PBOOL AddressValid
- );
- PSTR
- DbgpX86PrintMnemonic (
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86GetInstructionComponents (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86GetInstructionParameters (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction,
- PBOOL ModRmExists,
- PBOOL SibExists,
- PULONG DisplacementSize,
- PULONG ImmediateSize
- );
- PSTR
- DbgpX86GetControlRegister (
- BYTE ModRm
- );
- PSTR
- DbgpX86GetDebugRegister (
- BYTE ModRm
- );
- PSTR
- DbgpX86GetSegmentRegister (
- BYTE ModRm
- );
- PSTR
- DbgpX86GetGenericRegister (
- X86_REGISTER_VALUE RegisterNumber,
- CHAR Type
- );
- VOID
- DbgpX86GetDisplacement (
- PX86_INSTRUCTION Instruction,
- PSTR Buffer,
- PLONGLONG DisplacementValue
- );
- PX86_INSTRUCTION_DEFINITION
- DbgpX86GetTwoByteInstruction (
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86DecodeFloatingPointInstruction (
- PX86_INSTRUCTION Instruction
- );
- //
- // ------------------------------------------------------------------ Functions
- //
- BOOL
- DbgpX86Disassemble (
- ULONGLONG InstructionPointer,
- PBYTE InstructionStream,
- PSTR Buffer,
- ULONG BufferLength,
- PDISASSEMBLED_INSTRUCTION Disassembly
- )
- /*++
- Routine Description:
- This routine decodes one instruction from an IA-32 binary instruction
- stream into a human readable form.
- Arguments:
- InstructionPointer - Supplies the instruction pointer for the start of the
- instruction stream.
- InstructionStream - Supplies a pointer to the binary instruction stream.
- Buffer - Supplies a pointer to the buffer where the human
- readable strings will be printed. This buffer must be allocated by the
- caller.
- BufferLength - Supplies the length of the supplied buffer.
- Disassembly - Supplies a pointer to the structure that will receive
- information about the instruction.
- Return Value:
- TRUE on success.
- FALSE if the instruction was unknown.
- --*/
- {
- ULONGLONG Address;
- BOOL AddressValid;
- X86_INSTRUCTION Instruction;
- PSTR Mnemonic;
- BOOL Result;
- PSTR ThirdOperandFormat;
- if ((Disassembly == NULL) || (Buffer == NULL)) {
- return FALSE;
- }
- memset(Buffer, 0, BufferLength);
- memset(Disassembly, 0, sizeof(DISASSEMBLED_INSTRUCTION));
- //
- // Dissect the instruction into more managable components.
- //
- Result = DbgpX86GetInstructionComponents(InstructionStream, &Instruction);
- if (Result == FALSE) {
- goto DisassembleEnd;
- }
- Disassembly->BinaryLength = Instruction.Length;
- //
- // Print the mnemonic.
- //
- Mnemonic = DbgpX86PrintMnemonic(&Instruction);
- if ((Mnemonic == NULL) || (strlen(Mnemonic) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // Copy the mnemonic into the buffer, and advance the buffer to the next
- // free spot.
- //
- Disassembly->Mnemonic = Buffer;
- strcpy(Disassembly->Mnemonic, Mnemonic);
- Buffer += strlen(Mnemonic) + 1;
- BufferLength -= (strlen(Mnemonic) + 1);
- //
- // Get the destination operand.
- //
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- Instruction.Definition.Target,
- DbgX86DisassemblyBuffer,
- X86_WORKING_BUFFER_SIZE,
- &Address,
- &AddressValid);
- if ((Result == FALSE) ||
- (strlen(DbgX86DisassemblyBuffer) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // If an address came out of that, plug it into the result.
- //
- if (AddressValid != FALSE) {
- Disassembly->OperandAddress = Address;
- Disassembly->AddressIsValid = TRUE;
- Disassembly->AddressIsDestination = TRUE;
- }
- //
- // Copy the operand into the buffer, and advance the buffer.
- //
- Disassembly->DestinationOperand = Buffer;
- strcpy(Disassembly->DestinationOperand, DbgX86DisassemblyBuffer);
- Buffer += strlen(DbgX86DisassemblyBuffer) + 1;
- BufferLength -= (strlen(DbgX86DisassemblyBuffer) + 1);
- //
- // Get the source operand.
- //
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- Instruction.Definition.Source,
- DbgX86DisassemblyBuffer,
- X86_WORKING_BUFFER_SIZE,
- &Address,
- &AddressValid);
- if ((Result == FALSE) ||
- (strlen(DbgX86DisassemblyBuffer) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // If an address came out of the operand, plug it into the result.
- //
- if (AddressValid != FALSE) {
- Disassembly->OperandAddress = Address;
- Disassembly->AddressIsValid = TRUE;
- Disassembly->AddressIsDestination = FALSE;
- }
- //
- // Copy the operand into the buffer, and advance the buffer.
- //
- if (strlen(DbgX86DisassemblyBuffer) > 0) {
- Disassembly->SourceOperand = Buffer;
- strcpy(Disassembly->SourceOperand, DbgX86DisassemblyBuffer);
- Buffer += strlen(DbgX86DisassemblyBuffer) + 1;
- BufferLength -= (strlen(DbgX86DisassemblyBuffer) - 1);
- }
- //
- // Handle the MUL, SHLD, and SHRD instructions, which have 3 operands.
- //
- ThirdOperandFormat = NULL;
- if (Instruction.Opcode == X86_OPCODE1_IMUL1) {
- ThirdOperandFormat = "Iz";
- } else if (Instruction.Opcode == X86_OPCODE1_IMUL2) {
- ThirdOperandFormat = "Ib";
- } else if ((Instruction.Opcode == X86_ESCAPE_OPCODE) &&
- ((Instruction.Opcode2 == X86_OPCODE2_SHLD1) ||
- (Instruction.Opcode2 == X86_OPCODE2_SHRD1))) {
- ThirdOperandFormat = "Ib";
- } else if ((Instruction.Opcode == X86_ESCAPE_OPCODE) &&
- ((Instruction.Opcode2 == X86_OPCODE2_SHLD2) ||
- (Instruction.Opcode2 == X86_OPCODE2_SHRD2))) {
- ThirdOperandFormat = "!bcl";
- }
- if (ThirdOperandFormat != NULL) {
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- ThirdOperandFormat,
- DbgX86DisassemblyBuffer,
- X86_WORKING_BUFFER_SIZE,
- &Address,
- &AddressValid);
- if ((Result == FALSE) ||
- (strlen(DbgX86DisassemblyBuffer) > BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- Disassembly->ThirdOperand = Buffer;
- strcpy(Disassembly->ThirdOperand, DbgX86DisassemblyBuffer);
- }
- DisassembleEnd:
- return Result;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- BOOL
- DbgpX86PrintOperand (
- ULONGLONG InstructionPointer,
- PX86_INSTRUCTION Instruction,
- PSTR OperandFormat,
- PSTR Operand,
- ULONG BufferLength,
- PULONGLONG Address,
- PBOOL AddressValid
- )
- /*++
- Routine Description:
- This routine prints an operand in an IA instruction stream depending on the
- supplied format.
- Arguments:
- InstructionPointer - Supplies the instruction pointer for the instruction
- being disassembled.
- Instruction - Supplies a pointer to the instruction structure.
- OperandFormat - Supplies the format of the operand in two or more
- characters. These are largely compatible with the Intel Opcode
- Encodings, except for the ! prefix, which indicates an absolute
- register name.
- Operand - Supplies a pointer to the string that will receive the human
- readable operand.
- BufferLength - Supplies the length of the supplied buffer.
- Address - Supplies a pointer that receives the memory address encoded in the
- operand.
- AddressValid - Supplies a pointer that receives whether or not the value
- store in the Address parameter is valid.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- PSTR Base;
- BYTE BaseValue;
- PSTR Index;
- BYTE IndexValue;
- X86_MOD_VALUE Mod;
- X86_REGISTER_VALUE Register;
- PSTR RegisterString;
- X86_REGISTER_VALUE Rm;
- ULONG Scale;
- CHAR Type;
- CHAR Width;
- Base = NULL;
- Index = NULL;
- IndexValue = 0xFF;
- Scale = 0;
- RegisterString = NULL;
- //
- // Start by doing some parameter checking.
- //
- if ((Operand == NULL) || BufferLength == 0) {
- return FALSE;
- }
- strcpy(Operand, "");
- strcpy(DbgX86OperandBuffer, "");
- *Address = 0ULL;
- *AddressValid = FALSE;
- if (strlen(OperandFormat) < 2) {
- return TRUE;
- }
- Type = OperandFormat[0];
- Width = OperandFormat[1];
- //
- // 'd' means dword, which gets translated to long here for simplicity.
- //
- if (Width == 'd') {
- Width = X86_WIDTH_LONG;
- }
- //
- // If the width is variable, it is probably a dword unless an override is
- // specified.
- //
- if ((Width == 'v') || (Width == 'z')) {
- Width = X86_WIDTH_LONG;
- if ((Instruction->OperandOverride == TRUE) ||
- (Instruction->AddressOverride == TRUE)) {
- Width = X86_WIDTH_WORD;
- }
- }
- switch (Type) {
- //
- // The ! encoding indicates that a register is hardcoded. Unless an override
- // is set, append an e to the beginning of the hardcoded register (to make
- // ax into eax).
- //
- case '!':
- if ((Width == 'r') || (Width == 'e')) {
- if ((Instruction->ImmediateSize == 0) &&
- (Instruction->OperandOverride == FALSE)) {
- strcat(Operand, "e");
- } else if (Instruction->ImmediateSize == 4) {
- strcat(Operand, "e");
- }
- }
- strcat(Operand, OperandFormat + 2);
- break;
- //
- // A - Direct address, no mod R/M byte; address of operand is encoded in
- // instruction. No base, index, or scaling can be applied.
- //
- case 'A':
- sprintf(DbgX86OperandBuffer, "[0x%x]", Instruction->Immediate);
- strcat(Operand, DbgX86OperandBuffer);
- *Address = Instruction->Immediate;
- *AddressValid = TRUE;
- break;
- //
- // C - Reg field of mod R/M byte selects a control register.
- //
- case 'C':
- sprintf(DbgX86OperandBuffer,
- "%s",
- DbgpX86GetControlRegister(Instruction->ModRm));
- strcat(Operand, DbgX86OperandBuffer);
- break;
- //
- // D - Reg field of mod R/M byte selects a debug register.
- //
- case 'D':
- sprintf(DbgX86OperandBuffer, "%s",
- DbgpX86GetDebugRegister(Instruction->ModRm));
- strcat(Operand, DbgX86OperandBuffer);
- break;
- //
- // E - Mod R/M bytes follows opcode and specifies operand. Operand is either
- // a general register or a memory address. If it is a memory address, the
- // address is computed from a segment register and any of the following
- // values: a base register, an index register, a scaling factor, and a
- // displacement.
- // M - Mod R/M byte may only refer to memory.
- //
- case 'E':
- case 'M':
- Mod = (Instruction->ModRm & X86_MOD_MASK) >> X86_MOD_SHIFT;
- Rm = (Instruction->ModRm & X86_RM_MASK) >> X86_RM_SHIFT;
- if (Mod == X86ModValueRegister) {
- if (Type == 'M') {
- return FALSE;
- }
- RegisterString = DbgpX86GetGenericRegister(Rm, Width);
- } else {
- //
- // An R/M value of 4 actually indicates an SIB byte is present, not
- // ESP.
- //
- if (Rm == X86RegisterValueEsp) {
- Rm = X86RegisterValueScaleIndexBase;
- BaseValue = (Instruction->Sib & X86_BASE_MASK) >>
- X86_BASE_SHIFT;
- IndexValue = (Instruction->Sib & X86_INDEX_MASK) >>
- X86_INDEX_SHIFT;
- Base = DbgpX86GetGenericRegister(BaseValue, X86_WIDTH_LONG);
- Index = DbgpX86GetGenericRegister(IndexValue, X86_WIDTH_LONG);
- //
- // A base value of 5 (ebp) indicates that the base field is not
- // used, and a displacement is present. The Mod field then
- // specifies the size of the displacement.
- //
- if (BaseValue == X86RegisterValueEbp) {
- Base = "";
- sprintf(DbgX86OperandBuffer,
- "0x%x",
- Instruction->Displacement);
- strcat(Operand, DbgX86OperandBuffer);
- }
- //
- // Raise the scale to 2^(Scale).
- //
- Scale = (Instruction->Sib & X86_SCALE_MASK) >> X86_SCALE_SHIFT;
- if (Scale == 0) {
- Scale = 1;
- } else if (Scale == 1) {
- Scale = 2;
- } else if (Scale == 2) {
- Scale = 4;
- } else if (Scale == 3) {
- Scale = 8;
- }
- } else if ((Mod == X86ModValueNoDisplacement) &&
- (Rm == X86RegisterValueEbp)) {
- Rm = X86RegisterValueDisplacement32;
- } else {
- RegisterString = DbgpX86GetGenericRegister(Rm, X86_WIDTH_LONG);
- }
- }
- //
- // The operand is simply a register.
- //
- if (Mod == X86ModValueRegister) {
- strcat(Operand, RegisterString);
- //
- // The operand is an address with a scale/index/base.
- //
- } else if (Rm == X86RegisterValueScaleIndexBase) {
- sprintf(DbgX86OperandBuffer, "[%s", Base);
- strcat(Operand, DbgX86OperandBuffer);
- //
- // An index of 4 indicates that the index and scale fields are not
- // used.
- //
- if (IndexValue != 4) {
- if (strlen(Base) != 0) {
- strcat(Operand, "+");
- }
- sprintf(DbgX86OperandBuffer, "%s*%d", Index, Scale);
- strcat(Operand, DbgX86OperandBuffer);
- }
- DbgpX86GetDisplacement(Instruction, DbgX86OperandBuffer, NULL);
- strcat(Operand, DbgX86OperandBuffer);
- strcat(Operand, "]");
- //
- // The operand is a 32-bit address.
- //
- } else if (Rm == X86RegisterValueDisplacement32) {
- sprintf(DbgX86OperandBuffer, "[0x%x]", Instruction->Displacement);
- strcat(Operand, DbgX86OperandBuffer);
- *Address = Instruction->Displacement;
- *AddressValid = TRUE;
- //
- // The operand is an address in a register, possibly with some
- // additional displacement.
- //
- } else {
- sprintf(DbgX86OperandBuffer, "[%s", RegisterString);
- strcat(Operand, DbgX86OperandBuffer);
- DbgpX86GetDisplacement(Instruction, DbgX86OperandBuffer, NULL);
- strcat(Operand, DbgX86OperandBuffer);
- strcat(Operand, "]");
- }
- break;
- //
- // F - EFLAGS register.
- //
- case 'F':
- strcat(Operand, "eflags");
- break;
- //
- // G - Reg field of Mod R/M byte selects a general register.
- //
- case 'G':
- Register = (Instruction->ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- strcat(Operand, DbgpX86GetGenericRegister(Register, Width));
- break;
- //
- // I - Immediate data: value of operand is encoded in Immediate field.
- // O - Direct offset: no ModR/M byte. Offset of operand is encoded in
- // instruction. No Base/Index/Scale can be applied.
- //
- case 'I':
- case 'O':
- sprintf(DbgX86OperandBuffer, "0x%x", Instruction->Immediate);
- strcat(Operand, DbgX86OperandBuffer);
- break;
- //
- // J - Instruction contains a relative offset to be added to the instruction
- // pointer.
- //
- case 'J':
- DbgpX86GetDisplacement(Instruction,
- DbgX86OperandBuffer,
- (PLONGLONG)Address);
- *Address += (InstructionPointer + Instruction->Length);
- sprintf(DbgX86OperandBuffer, "[0x%x]", *Address);
- strcat(Operand, DbgX86OperandBuffer);
- *AddressValid = TRUE;
- break;
- //
- // R - R/M field of modR/M byte selects a general register. Mod field should
- // be set to 11.
- //
- case 'R':
- Mod = (Instruction->ModRm & X86_MOD_MASK) >> X86_MOD_SHIFT;
- Rm = (Instruction->ModRm & X86_RM_MASK) >> X86_RM_SHIFT;
- if (Mod != X86ModValueRegister) {
- return FALSE;
- }
- strcat(Operand, DbgpX86GetGenericRegister(Rm, Width));
- break;
- //
- // S - Reg field of ModR/M byte selects a segment register.
- //
- case 'S':
- strcat(Operand, DbgpX86GetSegmentRegister(Instruction->ModRm));
- break;
- //
- // X - Memory addressed by DS:SI register pair (eg. MOVS CMPS, OUTS, LODS).
- //
- case 'X':
- strcat(Operand, "DS:[esi]");
- break;
- //
- // Y - Memory addressed by ES:DI register pair (eg. MOVS INS, STOS, SCAS).
- //
- case 'Y':
- strcat(Operand, "ES:[edi]");
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- PSTR
- DbgpX86PrintMnemonic (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine prints an instruction mnemonic.
- Arguments:
- Instruction - Supplies a pointer to the instruction structure.
- Return Value:
- A pointer to the mnemonic on success.
- NULL on failure.
- --*/
- {
- BYTE RegByte;
- if (Instruction == NULL) {
- return NULL;
- }
- if (Instruction->Definition.Group == 0) {
- return Instruction->Definition.Mnemonic;
- }
- RegByte = (Instruction->ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- switch (Instruction->Definition.Group) {
- case 1:
- return DbgX86Group1Instructions[RegByte].Mnemonic;
- case 2:
- return DbgX86Group2Instructions[RegByte].Mnemonic;
- case 3:
- return DbgX86Group3Instructions[RegByte].Mnemonic;
- case 0x3A:
- return DbgX86Group3AInstructions[RegByte].Mnemonic;
- case 4:
- if (RegByte >= X86_GROUP_4_INSTRUCTION_COUNT) {
- return NULL;
- }
- return DbgX86Group4Instructions[RegByte].Mnemonic;
- case 5:
- if (RegByte >= X86_GROUP_5_INSTRUCTION_COUNT) {
- return "(bad)";
- }
- return DbgX86Group5Instructions[RegByte].Mnemonic;
- case 10:
- case 12:
- if (RegByte != 0) {
- return "(bad)";
- }
- return Instruction->Definition.Mnemonic;
- case 15:
- return DbgX86Group15Instructions[RegByte].Mnemonic;
- }
- return NULL;
- }
- BOOL
- DbgpX86GetInstructionComponents (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine reads an instruction stream and decomposes it into its
- respective components.
- Arguments:
- InstructionStream - Supplies a pointer to the raw binary instruction stream.
- Instruction - Supplies a pointer to the structure that will accept the
- instruction decomposition.
- Return Value:
- TRUE on success.
- FALSE otherwise.
- --*/
- {
- ULONG AlternateCount;
- ULONG AlternateIndex;
- ULONG Base;
- PBYTE Beginning;
- PBYTE CurrentPrefix;
- ULONG DisplacementSize;
- ULONG Group;
- ULONG ImmediateSize;
- ULONG Mod;
- BOOL ModRmExists;
- UCHAR Opcode3;
- BYTE RegByte;
- BOOL Result;
- BOOL SibExists;
- PX86_INSTRUCTION_DEFINITION TopLevelDefinition;
- PX86_INSTRUCTION_DEFINITION TwoByteInstruction;
- if (Instruction == NULL) {
- return FALSE;
- }
- CurrentPrefix = &(Instruction->Prefix[0]);
- Beginning = InstructionStream;
- Result = TRUE;
- memset(Instruction, 0, sizeof(X86_INSTRUCTION));
- //
- // Begin by handling any prefixes. The prefixes are: F0 (LOCK), F2 (REP),
- // F3 (REP), 2E (CS), 36 (SS), 3E (DS), 26 (ES), 64 (FS), 65 (GS),
- // 66 (Operand-size override), 67 (Address-size override)).
- //
- while ((*InstructionStream == X86_PREFIX_LOCK) ||
- (*InstructionStream == X86_PREFIX_REP1) ||
- (*InstructionStream == X86_PREFIX_REP2) ||
- ((*InstructionStream & X86_PREFIX_FS_GS_OVERRIDE_MASK) ==
- X86_PREFIX_FS_GS_OVERRIDE_VALUE) ||
- (*InstructionStream == X86_PREFIX_CS) ||
- (*InstructionStream == X86_PREFIX_DS) ||
- (*InstructionStream == X86_PREFIX_ES) ||
- (*InstructionStream == X86_PREFIX_SS)) {
- if (*InstructionStream == X86_OPERAND_OVERRIDE) {
- Instruction->OperandOverride = TRUE;
- } else if (*InstructionStream == X86_ADDRESS_OVERRIDE) {
- Instruction->AddressOverride = TRUE;
- }
- *CurrentPrefix = *InstructionStream;
- CurrentPrefix += 1;
- InstructionStream += 1;
- Instruction->Length += 1;
- //
- // No more than 4 prefixes are allowed in one instruction.
- //
- if (Instruction->Length == X86_MAX_PREFIXES) {
- break;
- }
- }
- Instruction->Opcode = *InstructionStream;
- Instruction->Length += 1;
- InstructionStream += 1;
- //
- // Check for a two byte opcode.
- //
- if (Instruction->Opcode == X86_ESCAPE_OPCODE) {
- Instruction->Opcode2 = *InstructionStream;
- Instruction->Length += 1;
- InstructionStream += 1;
- TwoByteInstruction = DbgpX86GetTwoByteInstruction(Instruction);
- if (TwoByteInstruction == NULL) {
- Result = FALSE;
- goto GetInstructionComponentsEnd;
- }
- TopLevelDefinition = TwoByteInstruction;
- } else {
- TopLevelDefinition = &(DbgX86Instructions[Instruction->Opcode]);
- }
- //
- // Modify the instruction definition for groups. If the opcode is in a
- // group, then it must have a modR/M byte, so cheat a little and get it.
- //
- Instruction->Definition = *TopLevelDefinition;
- Group = Instruction->Definition.Group;
- if ((Group != 0) && (Group != X86_INVALID_GROUP)) {
- RegByte = (*InstructionStream & X86_REG_MASK) >> X86_REG_SHIFT;
- switch (Instruction->Definition.Group) {
- case 1:
- case 2:
- break;
- case 3:
- Instruction->Definition.Source =
- DbgX86Group3Instructions[RegByte].Source;
- break;
- case 0x3A:
- Instruction->Definition.Source =
- DbgX86Group3AInstructions[RegByte].Source;
- break;
- case 4:
- case 5:
- break;
- case 6:
- if (RegByte >= X86_GROUP_6_INSTRUCTION_COUNT) {
- Result = FALSE;
- goto GetInstructionComponentsEnd;
- }
- Instruction->Definition = DbgX86Group6Instructions[RegByte];
- break;
- case 7:
- Instruction->Definition = DbgX86Group7Instructions[RegByte];
- //
- // There are a bunch of alternate encoding instructions hidden
- // behind 0F 01, go look for them.
- //
- if (RegByte == 1) {
- Opcode3 = *InstructionStream;
- AlternateCount = sizeof(DbgX860F01Alternates) /
- sizeof(DbgX860F01Alternates[0]);
- for (AlternateIndex = 0;
- AlternateIndex < AlternateCount;
- AlternateIndex += 1) {
- if (DbgX860F01Alternates[AlternateIndex].Opcode ==
- Opcode3) {
- Instruction->Definition =
- DbgX860F01Alternates[AlternateIndex].Instruction;
- break;
- }
- }
- }
- break;
- case 8:
- if (RegByte < X86_GROUP_8_FIRST_INSTRUCTION) {
- Result = FALSE;
- goto GetInstructionComponentsEnd;
- }
- Instruction->Definition = DbgX86Group8Instructions[RegByte];
- break;
- case 9:
- if (RegByte != X86_GROUP_9_ONLY_VALID_INSTRUCTION) {
- Result = FALSE;
- goto GetInstructionComponentsEnd;
- }
- Instruction->Definition = DbgX86Group9Instructions[RegByte];
- break;
- case 10:
- case 12:
- case 0x87:
- break;
- case 15:
- Instruction->Definition = DbgX86Group15Instructions[RegByte];
- break;
- default:
- assert(FALSE);
- break;
- }
- }
- //
- // Get the structure of the instruction.
- //
- Result = DbgpX86GetInstructionParameters(InstructionStream,
- Instruction,
- &ModRmExists,
- &SibExists,
- &DisplacementSize,
- &ImmediateSize);
- if (Result == FALSE) {
- goto GetInstructionComponentsEnd;
- }
- if (Group != 0) {
- ModRmExists = TRUE;
- }
- //
- // Populate the various pieces of the instruction.
- //
- Instruction->DisplacementSize = DisplacementSize;
- Instruction->ImmediateSize = ImmediateSize;
- if (ModRmExists == TRUE) {
- Instruction->ModRm = *InstructionStream;
- InstructionStream += 1;
- }
- if (SibExists == TRUE) {
- Instruction->Sib = *InstructionStream;
- InstructionStream += 1;
- //
- // Check to see if the SIB byte requires a displacement. EBP is not a
- // valid base, since that can be specified in the Mod bits.
- //
- Base = (Instruction->Sib & X86_BASE_MASK) >> X86_BASE_SHIFT;
- Mod = (Instruction->ModRm & X86_MOD_MASK) >> X86_MOD_SHIFT;
- if (Base == X86RegisterValueEbp) {
- if (Mod == X86ModValueDisplacement8) {
- DisplacementSize = 1;
- } else {
- DisplacementSize = 4;
- }
- }
- }
- //
- // Grab the displacement and immediates from the instruction stream if
- // they're there.
- //
- if (DisplacementSize != 0) {
- memcpy(&(Instruction->Displacement),
- InstructionStream,
- DisplacementSize);
- InstructionStream += DisplacementSize;
- }
- if (ImmediateSize != 0) {
- memcpy(&(Instruction->Immediate), InstructionStream, ImmediateSize);
- InstructionStream += ImmediateSize;
- }
- Instruction->Length = InstructionStream - Beginning;
- //
- // If it's an x87 floating point instruction, decode it now that the
- // ModR/M byte was grabbed.
- //
- if (Group == 0x87) {
- Result = DbgpX86DecodeFloatingPointInstruction(Instruction);
- if (Result == FALSE) {
- goto GetInstructionComponentsEnd;
- }
- }
- GetInstructionComponentsEnd:
- return Result;
- }
- BOOL
- DbgpX86GetInstructionParameters (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction,
- PBOOL ModRmExists,
- PBOOL SibExists,
- PULONG DisplacementSize,
- PULONG ImmediateSize
- )
- /*++
- Routine Description:
- This routine determines the format of the rest of the instruction based on
- the opcode, any prefixes, and possibly the ModRM byte.
- Arguments:
- InstructionStream - Supplies a pointer to the binary instruction stream,
- after the prefixes and opcode.
- Instruction - Supplies a pointer to an instruction. The Prefixes, Opcode,
- and Definition must be filled out.
- ModRmExists - Supplies a pointer where a boolean will be returned
- indicating whether or not a ModRM byte is present.
- SibExists - Supplies a pointer where a boolean will be returned indicating
- whether or not a Scale/Index/Base byte is present in the instruction
- stream.
- DisplacementSize - Supplies a pointer where the size of the Displacement
- value will be returned. 0 indicates there is no displacement in the
- instruction.
- ImmediateSize - Supplies a pointer where the size of the Immediate field
- in the instruction will be returned. 0 indicates there is no Immediate
- field in the instruction.
- Return Value:
- TRUE on success.
- FALSE otherwise.
- --*/
- {
- X86_MOD_VALUE Mod;
- BYTE ModRm;
- ULONG ParseCount;
- BYTE RmValue;
- CHAR Type;
- CHAR Width;
- *ModRmExists = FALSE;
- *SibExists = FALSE;
- *DisplacementSize = 0;
- *ImmediateSize = 0;
- if (Instruction->Definition.Target[0] == '\0') {
- return TRUE;
- }
- Type = Instruction->Definition.Target[0];
- Width = Instruction->Definition.Target[1];
- ParseCount = 0;
- do {
- switch (Type) {
- //
- // A - Direct address. No Mod/RM, Immediate specifies address. No SIB.
- //
- case 'A':
- *ImmediateSize = 4;
- break;
- //
- // C - Control register in ModR/M.
- // D - Debug register in ModR/M.
- // S - Segment register in Reg field of ModR/M.
- // T - Test register in ModR/M.
- // V - SIMD floating point register in ModR/M.
- //
- case 'C':
- case 'D':
- case 'S':
- case 'T':
- case 'V':
- *ModRmExists = TRUE;
- break;
- //
- // E - Mod R/M bytes follows opcode and specifies operand. Operand is
- // either a general register or a memory address. If it is a memory
- // address, the address is computed from a segment register and any of
- // the following values: a base register, an index register, a scaling
- // factor, and a displacement.
- // M - Mod R/M byte may only refer to memory.
- // R - Mod R/M byte may only refer to a general register.
- //
- case 'E':
- case 'M':
- case 'R':
- *ModRmExists = TRUE;
- ModRm = *InstructionStream;
- Mod = (ModRm & X86_MOD_MASK) >> X86_MOD_SHIFT;
- RmValue = (ModRm & X86_RM_MASK) >> X86_RM_SHIFT;
- if (Mod != X86ModValueRegister) {
- //
- // An R/M value of 4 actually indicates an SIB byte is present,
- // not ESP.
- //
- if (RmValue == X86RegisterValueEsp) {
- RmValue = X86RegisterValueScaleIndexBase;
- *SibExists = TRUE;
- }
- //
- // An R/M value of 5 when Mod is 0 means that the address is
- // actually just a 32bit displacment.
- //
- if ((Mod == X86ModValueNoDisplacement) &&
- (RmValue == X86RegisterValueEbp)) {
- RmValue = X86RegisterValueDisplacement32;
- *DisplacementSize = 4;
- }
- }
- //
- // Get any displacements as specified by the MOD bits.
- //
- if (Mod == X86ModValueDisplacement8) {
- *DisplacementSize = 1;
- } else if (Mod == X86ModValueDisplacement32) {
- *DisplacementSize = 4;
- }
- break;
- //
- // F - Flags register. No additional bytes.
- // X - Memory addressed by DS:SI pair.
- // Y - Memory addressed by ES:DI pair.
- // ! - Hardcoded register.
- //
- case 'F':
- case 'X':
- case 'Y':
- case '!':
- break;
- //
- // G - General register specified in Reg field of ModR/M byte.
- //
- case 'G':
- *ModRmExists = TRUE;
- break;
- //
- // I - Immediate data is encoded in subsequent bytes.
- //
- case 'I':
- switch (Width) {
- case X86_WIDTH_BYTE:
- *ImmediateSize = 1;
- break;
- case X86_WIDTH_WORD:
- *ImmediateSize = 2;
- break;
- case X86_WIDTH_LONG:
- *ImmediateSize = 4;
- break;
- case 'v':
- case 'z':
- *ImmediateSize = 4;
- if (Instruction->OperandOverride == TRUE) {
- *ImmediateSize = 2;
- }
- break;
- }
- break;
- //
- // O - Direct Offset. No ModR/M byte, offset of operand is encoded in
- // instruction. No SIB.
- //
- case 'O':
- *ImmediateSize = 4;
- if (Instruction->AddressOverride != FALSE) {
- *ImmediateSize = 2;
- }
- break;
- //
- // J - Instruction contains relative offset.
- //
- case 'J':
- switch (Width) {
- case X86_WIDTH_BYTE:
- *DisplacementSize = 1;
- break;
- case X86_WIDTH_WORD:
- *DisplacementSize = 2;
- break;
- case X86_WIDTH_LONG:
- *DisplacementSize = 4;
- break;
- case 'v':
- case 'z':
- *DisplacementSize = 4;
- if (Instruction->AddressOverride == TRUE) {
- *DisplacementSize = 2;
- }
- break;
- }
- break;
- default:
- return FALSE;
- }
- //
- // Now that the target has been processed, loop again to process the
- // source.
- //
- ParseCount += 1;
- if (Instruction->Definition.Source[0] == '\0') {
- break;
- }
- Type = Instruction->Definition.Source[0];
- Width = Instruction->Definition.Source[1];
- } while (ParseCount < 2);
- //
- // Handle the special instructions that actually have three operands.
- //
- if (Instruction->Opcode == X86_OPCODE1_IMUL1) {
- *ImmediateSize = 4;
- if (Instruction->OperandOverride == TRUE) {
- *ImmediateSize = 2;
- }
- }
- if (Instruction->Opcode == X86_OPCODE1_IMUL2) {
- *ImmediateSize = 1;
- }
- if ((Instruction->Opcode == X86_ESCAPE_OPCODE) &&
- ((Instruction->Opcode2 == X86_OPCODE2_SHLD1) ||
- (Instruction->Opcode2 == X86_OPCODE2_SHRD1))) {
- *ImmediateSize = 1;
- }
- return TRUE;
- }
- PSTR
- DbgpX86GetControlRegister (
- BYTE ModRm
- )
- /*++
- Routine Description:
- This routine reads the REG bits of a ModR/M byte and returns a string
- representing the control register in those bits.
- Arguments:
- ModRm - Supplies the ModR/M byte of the instruction. Only bits 5:3 are used.
- Return Value:
- The control register specifed, in string form.
- --*/
- {
- BYTE RegisterNumber;
- RegisterNumber = (ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- switch (RegisterNumber) {
- case 0:
- return "cr0";
- break;
- case 2:
- return "cr2";
- break;
- case 3:
- return "cr3";
- break;
- case 4:
- return "cr4";
- break;
- }
- return "ERR";
- }
- PSTR
- DbgpX86GetDebugRegister (
- BYTE ModRm
- )
- /*++
- Routine Description:
- This routine reads the REG bits of a ModR/M byte and returns a string
- representing the debug register in those bits.
- Arguments:
- ModRm - Supplies the ModR/M byte of the instruction. Only bits 5:3 are used.
- Return Value:
- The debug register specifed, in string form.
- --*/
- {
- BYTE RegisterNumber;
- RegisterNumber = (ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- if (RegisterNumber >= X86_DEBUG_REGISTER_COUNT) {
- return "ERR";
- }
- return DbgX86DebugRegisterNames[RegisterNumber];
- }
- PSTR
- DbgpX86GetSegmentRegister (
- BYTE ModRm
- )
- /*++
- Routine Description:
- This routine reads the REG bits of a ModR/M byte and returns a string
- representing the segment register in those bits.
- Arguments:
- ModRm - Supplies the ModR/M byte of the instruction. Only bits 5:3 are used.
- Return Value:
- The segment register specifed, in string form.
- --*/
- {
- BYTE RegisterNumber;
- RegisterNumber = (ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- if (RegisterNumber >= X86_SEGMENT_REGISTER_COUNT) {
- return "ER";
- }
- return DbgX86SegmentRegisterNames[RegisterNumber];
- }
- PSTR
- DbgpX86GetGenericRegister (
- X86_REGISTER_VALUE RegisterNumber,
- CHAR Type
- )
- /*++
- Routine Description:
- This routine reads a register number and a width and returns a string
- representing that register. The register number should be in the same format
- as specified in the REG bits of the ModR/M byte.
- Arguments:
- RegisterNumber - Supplies which register to print out, as specified by the
- REG bits of the ModR/M byte.
- Type - Supplies a width or special register format.
- Return Value:
- The register specifed, in string form.
- --*/
- {
- if (RegisterNumber >= X86_REGISTER_NAME_COUNT) {
- return "ERR";
- }
- switch (Type) {
- case X86_WIDTH_BYTE:
- return DbgX86RegisterNames8Bit[RegisterNumber];
- case X86_WIDTH_WORD:
- return DbgX86RegisterNames16Bit[RegisterNumber];
- case X86_WIDTH_LONG:
- return DbgX86RegisterNames32Bit[RegisterNumber];
- case X86_FLOATING_POINT_REGISTER:
- return DbgX87RegisterNames[RegisterNumber];
- default:
- assert(FALSE);
- return "ERR";
- }
- }
- VOID
- DbgpX86GetDisplacement (
- PX86_INSTRUCTION Instruction,
- PSTR Buffer,
- PLONGLONG DisplacementValue
- )
- /*++
- Routine Description:
- This routine prints an address displacement value.
- Arguments:
- Instruction - Supplies a pointer to the instruction containing the
- displacement.
- Buffer - Supplies a pointer to the output buffer the displacement will be
- printed to.
- DisplacementValue - Supplies a pointer to the variable that will receive the
- numerical displacement value. This can be NULL.
- Return Value:
- The instruction displacement field, in string form.
- --*/
- {
- LONG Displacement;
- if ((Buffer == NULL) || (Instruction == NULL)) {
- return;
- }
- strcpy(Buffer, "");
- if (Instruction->Displacement == 0) {
- return;
- }
- switch (Instruction->DisplacementSize) {
- case 1:
- Displacement = (CHAR)Instruction->Displacement;
- break;
- case 2:
- Displacement = (SHORT)Instruction->Displacement;
- break;
- case 4:
- Displacement = (LONG)Instruction->Displacement;
- break;
- default:
- return;
- }
- if (Displacement < 0) {
- sprintf(Buffer, "-0x%x", -Displacement);
- } else {
- sprintf(Buffer, "+0x%x", Displacement);
- }
- if (DisplacementValue != NULL) {
- *DisplacementValue = Displacement;
- }
- }
- PX86_INSTRUCTION_DEFINITION
- DbgpX86GetTwoByteInstruction (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine finds a two-byte instruction definition corresponding to the
- instruction opcode and prefixes.
- Arguments:
- Instruction - Supplies a pointer to the instruction containing the
- two byte opcode and any prefixes.
- Return Value:
- Returns a pointer to the instruction definition, or NULL if one could not
- be found.
- --*/
- {
- PX86_INSTRUCTION_DEFINITION Definition;
- ULONG InstructionIndex;
- ULONG InstructionLength;
- ULONG PrefixIndex;
- PrefixIndex = 0;
- InstructionLength = sizeof(DbgX86TwoByteInstructions) /
- sizeof(DbgX86TwoByteInstructions[0]);
- //
- // First search through the array looking for a version with the first
- // corresponding prefix.
- //
- while (Instruction->Prefix[PrefixIndex] != 0) {
- InstructionIndex = 0;
- while (InstructionIndex < InstructionLength) {
- if ((DbgX86TwoByteInstructions[InstructionIndex].Prefix ==
- Instruction->Prefix[PrefixIndex]) &&
- (DbgX86TwoByteInstructions[InstructionIndex].Opcode ==
- Instruction->Opcode2)) {
- Definition =
- &(DbgX86TwoByteInstructions[InstructionIndex].Instruction);
- return Definition;
- }
- InstructionIndex += 1;
- }
- PrefixIndex += 1;
- }
- //
- // The search for the specific prefix instruction was not successful, or
- // no prefixes were present. Search for the opcode with a prefix of zero,
- // indicating that the prefix field is not applicable.
- //
- InstructionIndex = 0;
- while (InstructionIndex < InstructionLength) {
- if ((DbgX86TwoByteInstructions[InstructionIndex].Opcode ==
- Instruction->Opcode2) &&
- (DbgX86TwoByteInstructions[InstructionIndex].Prefix == 0)) {
- return &(DbgX86TwoByteInstructions[InstructionIndex].Instruction);
- }
- InstructionIndex += 1;
- }
- //
- // The search yielded no results. Return NULL.
- //
- return NULL;
- }
- BOOL
- DbgpX86DecodeFloatingPointInstruction (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine decodes the given x87 floating point instruction by
- manipulating the instruction definition.
- Arguments:
- Instruction - Supplies a pointer to the instruction.
- Return Value:
- TRUE on success.
- FALSE if the instruction is invalid. Well, let's be more PC and say that no
- instruction is "invalid", only "executionally challenged".
- --*/
- {
- BYTE Index;
- BYTE Mod;
- BYTE ModRm;
- BYTE Opcode;
- BYTE Opcode2;
- ModRm = Instruction->ModRm;
- Mod = (ModRm & X86_MOD_MASK) >> X86_MOD_SHIFT;
- Opcode = Instruction->Opcode - X87_ESCAPE_OFFSET;
- Opcode2 = (ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- //
- // Reset the group to 0 so that after this routine tweaks everything it
- // gets treated like a normal instruction.
- //
- Instruction->Definition.Group = 0;
- Instruction->Definition.Mnemonic = NULL;
- //
- // If the ModR/M byte does not specify a register, then use the big
- // table to figure out the mnemonic.
- //
- if (Mod != X86ModValueRegister) {
- Instruction->Definition.Mnemonic = DbgX87Instructions[Opcode][Opcode2];
- if (Instruction->Definition.Mnemonic == NULL) {
- return FALSE;
- }
- return TRUE;
- }
- switch (Opcode) {
- //
- // Handle D8 instructions.
- //
- case 0:
- Instruction->Definition.Mnemonic = DbgX87Instructions[0][Opcode2];
- //
- // The fcom and fcomp instructions take only ST(i). Everything else
- // has two operands, st, and st(i).
- //
- if ((ModRm & X87_FCOM_MASK) == X87_FCOM_OPCODE) {
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- } else {
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle D9 instructions.
- //
- case 1:
- switch (Opcode2) {
- //
- // C0-C7 is FLD ST(i).
- //
- case 0:
- Instruction->Definition.Mnemonic = X87_FLD_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // C8-CF is FXCH ST(i).
- //
- case 1:
- Instruction->Definition.Mnemonic = X87_FXCH_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // D0-D7 is just a NOP (really only at D0, but let it slide).
- //
- case 2:
- Instruction->Definition.Mnemonic = X87_NOP_MNEMONIC;
- Instruction->Definition.Target = "";
- break;
- //
- // D8-DF is FSTP1 ST(i).
- //
- case 3:
- Instruction->Definition.Mnemonic = X87_FSTP1_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // E0-FF is a grab bag of instructions with no operands.
- //
- default:
- Instruction->Definition.Mnemonic =
- DbgX87D9E0Instructions[ModRm - X87_D9_E0_OFFSET];
- Instruction->Definition.Target = "";
- break;
- }
- break;
- //
- // Handle DA instructions.
- //
- case 2:
- //
- // The fucompp instruction lives off by itself in a wasteland.
- //
- if (ModRm == X87_FUCOMPP_OPCODE) {
- Instruction->Definition.Mnemonic = X87_FUCOMPP_MNEMONIC;
- Instruction->Definition.Target = "";
- } else {
- //
- // There are 8 instructions (4 valid), each of which take the form
- // xxx ST, ST(i). So each instruction takes up 8 bytes.
- //
- Index = (ModRm & X87_DA_C0_MASK) >> X87_DA_CO_SHIFT;
- Instruction->Definition.Mnemonic = DbgX87DAC0Instructions[Index];
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle DB instructions.
- //
- case 3:
- Index = (ModRm & X87_DB_C0_MASK) >> X87_DB_C0_SHIFT;
- //
- // There's a small rash of inidividual instructions in the E0-E7
- // range.
- //
- if (Index == X87_DB_E0_INDEX) {
- Index = ModRm & X87_DB_E0_MASK;
- Instruction->Definition.Mnemonic = DbgX87DBE0Instructions[Index];
- Instruction->Definition.Target = "";
- //
- // Otherwise there are swaths of instructions that take up 8 bytes
- // each as they take the form xxx ST, ST(i).
- //
- } else {
- Instruction->Definition.Mnemonic = DbgX87DBC0Instructions[Index];
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // DC is the same as D8, except it handles doubles instead of singles
- // (floats). There's one other annoying detail which is that the FSUB and
- // FSUBR are switched above 0xC0. The same goes for FDIV and FDIVR.
- //
- case 4:
- Instruction->Definition.Mnemonic = DbgX87DCC0Instructions[Opcode2];
- //
- // The fcom and fcomp instructions take only ST(i). Everything else
- // has two operands, st, and st(i).
- //
- if ((ModRm & X87_FCOM_MASK) == X87_FCOM_OPCODE) {
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- } else {
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle DD instructions.
- //
- case 5:
- Instruction->Definition.Mnemonic = DbgX87DDC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // Handle DE instructions.
- //
- case 6:
- Instruction->Definition.Mnemonic = DbgX87DEC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- Instruction->Definition.Source = X87_ST0_TARGET;
- break;
- //
- // Handle DF instructions.
- //
- case 7:
- Index = (ModRm & X87_DF_C0_MASK) >> X87_DF_C0_SHIFT;
- //
- // There's a small rash of individual instructions in the E0-E7
- // range. They're pretty old school.
- //
- if (Index == X87_DF_E0_INDEX) {
- Index = ModRm & X87_DF_E0_MASK;
- if (Index < X87_DF_E0_COUNT) {
- Instruction->Definition.Mnemonic =
- DbgX87DFE0Instructions[Index];
- Instruction->Definition.Target = X87_DF_E0_TARGET;
- }
- } else {
- Instruction->Definition.Mnemonic = DbgX87DFC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- Instruction->Definition.Source = X87_ST0_TARGET;
- }
- break;
- //
- // This function was inappropriately called.
- //
- default:
- assert(FALSE);
- break;
- }
- if (Instruction->Definition.Mnemonic == NULL) {
- return FALSE;
- }
- return TRUE;
- }
|