📄 disasm-x86.c
字号:
/* * libDASM * * Copyright (C) 2000-2003 Patrick Alken * This library comes with absolutely NO WARRANTY * * Should you choose to use and/or modify this source code, please * do so under the terms of the GNU General Public License under which * this library is distributed. * * $Id: disasm-x86.c,v 1.3 2004/09/02 00:11:59 pa33 Exp $ */#include <stdio.h>#include <assert.h>#include <string.h>#include "args-x86.h"#include "common-x86.h"#include "disasm-x86.h"#include "modsib-x86.h"#include "operands-x86.h"#include "optab-x86.h"#include "prefix-x86.h"/* Top-level includes */#include "libDASM.h"static long x86findOpCode(struct disasmWorkspace *ws, unsigned char *data, char *outbuf, struct x86matchInfo *bestmatch);/*x86procDisasm() Disassemble one instructionInputs: ws - disasm workspace data - data to disassemble outbuf - buffer to store result address - address of this opcode in the file or memory; when given, relative addresses such as in a CALL opcode will be added to this to compute an exact target address.Return: number of bytes disassembled, or if an error occurs -1 and an error message goes in outbuf*/longx86procDisasm(struct disasmWorkspace *ws, unsigned char *data, char *outbuf, unsigned int address){ unsigned char *origdata; long bytesMatched; /* number of bytes matched to opcode */ struct x86matchInfo match; /* opcode matching data */ int ret; /* return result */ origdata = data; assert(data && outbuf); memset(&match, '\0', sizeof(struct x86matchInfo)); ws->prefixFlags = 0; ws->effectiveAddress = 0; bytesMatched = x86findOpCode(ws, data, outbuf, &match); if (bytesMatched < 0) { /* 'outbuf' will contain the error message */ return (bytesMatched); } else if (bytesMatched == 0) { /* No match found */ return (0); } /* * We found a good match */ data += bytesMatched; ret = x86constructArguments(ws, (unsigned char **) &data, &match, outbuf, address); if (ret) return (data - origdata); else return (-1);} /* x86procDisasm() *//*x86findOpCode() Attempt to locate best matching opcode for given string inthe x86OpCodes[] array.Inputs: ws - disasm workspace data - actual opcode outbuf - string in which to store error messages bestmatch - structure in which to store best matching opcodeReturn: Number of bytes matched if matching opcode is found 0 if no matching opcode found -1 if error encounteredSide effects: On a good match, 'bestmatch' is modified to point to the matching OpCode structure. On an error, -1 is returned and 'outbuf' is modified to contain the error message.Developer's Note: The optab.pl scripts sets up the array x86OpCodes[00..FF] with pointersto different opcode arrays each corresponding to one byte (00..FF). Thisbyte is the first byte of the opcode. These opcode arrays are calledOpCode_XX where XX is the first byte of the opcode. Since severaldifferent instructions could share the same first byte of their opcodes,the OpCode_XX arrays contain pointers to all instructions which haveXX as the first byte of their opcode. This function looks at data[0] (the first byte of the opcode) andjumps to the array defined by x86OpCodes[data[0]]. This array may containmany pointers to different instructions in the array Instructions[], butwe know they all share the same first byte of their opcodes. We thenproceed along the data[] array and compare those bytes withthe opcodes in the OpCode_XX array given by x86OpCodes[data[0]].*/static longx86findOpCode(struct disasmWorkspace *ws, unsigned char *data, char *outbuf, struct x86matchInfo *bestmatch){ struct x86OpCode **candidates; /* opcode candidates */ unsigned char index; /* index into x86OpCodes[] */ struct x86OpCode **OpPtr; /* pointer to an opcode candidate */ struct x86matchInfo matches[MAXBUF]; /* possible opcode matches */ int midx; /* index into matches[] */ long bytesMatched; /* bytes matched on some opcode */ unsigned char *codeptr; /* pointer to opcode string */ int regcode; /* register for +rb/+rw/+rd opcodes */ int fpucode; /* register for +i opcodes */ struct x86ModSibInfo msinfo; /* ModR/M and SIB information */ int exactMatch; /* set to 1 if we find exact match */ unsigned char prefBytes; /* number of bytes in prefix */ int pret; /* return value from x86testPrefix() */ int ii; /* looping */ int foundBestMatch; /* did we find the best match? */ int betterMatch; /* do we have a better match? */ assert(ws && data && outbuf && bestmatch); midx = 0; prefBytes = x86processPrefix(ws, data); data += prefBytes; index = (unsigned char) *data; /* * We cannot immediately assign candidates to x86OpCodes[*data] * since the first byte of the opcode may have been modified * by adding an integer between 0-7 to indicate a register code * (+rb/+rw/+rd/+i in the IAS manual). * * If this was the case, x86OpCodes[*data] will be NULL (unless * intel has instructions which share the first opcode byte * but one of them added a register code to their real first * byte - I haven't found any of these). */ while (!*x86OpCodes[index]) { /* * Keep decrementing index until we find the real first * byte of the opcode - do this no more than 7 times. */ --index; if (((unsigned char) *data - index) > 7) { /* * This should never happen - unless there exists * a string of 7+ consecutive numbers which aren't used * as the first byte of any opcode. */ sprintf(outbuf, "x86findOpCode: indices of x86OpCodes[] ranging from %d to %d are \ all NULL (looking for register code)", index, (unsigned char) *data); return (-1); } } /* while (!*x86OpCodes[index]) */ /* * Now our instruction candidates are the array x86OpCodes[index] */ candidates = x86OpCodes[index]; for (OpPtr = candidates; *OpPtr; ++OpPtr) { exactMatch = 0; regcode = (-1); fpucode = (-1); memset(&msinfo, '\0', sizeof(struct x86ModSibInfo)); /* * (*OpPtr)->mcode is the opcode string for the current * instruction we are checking */ codeptr = (unsigned char *) (*OpPtr)->mcode; if (*(codeptr + 1) == '\0') { /* * We are dealing with a one byte opcode: this case * warrants special attention. If the instruction is * defined with +rb/+rw/+rd/+i we need to determine * if something between 0-7 was added to the first * byte. */ if ((*OpPtr)->digit == REGCODE) /* +rb/+rw/+rd */ regcode = (unsigned char) *data - index; else if ((*OpPtr)->digit == FPUCODE) /* +i */ fpucode = (unsigned char) *data - index; else if (index != (unsigned char) *data) { /* * If index and *data do not match, it means our above loop * decremented index since OpCodes[*data] was empty. This * implies that the instruction we are disassembling is * defined with +rb/+rw/+rd/+i, but the current prospective * instruction is not defined this way, so it is a bad match. */ continue; } } /* * We have matched the first byte of 'data' to an opcode so * set bytesMatched to 1 */ bytesMatched = 1; /* * If there are more bytes to the opcode, we must check them * against 'data'. */ while (*++codeptr) { if (*codeptr == *(data + bytesMatched)) { /* * We just matched another byte of the opcode */ ++bytesMatched; /* * Check if this is the last opcode byte. If so, check * if this opcode has a +rb/+rw/+rd/+i flag. These flags * indicate that a value between 0-7 is added to the * last byte of the opcode. Since this is the last byte, * the value 0 must have been added. */ if (*(codeptr + 1) == '\0') { if ((*OpPtr)->digit == REGCODE) regcode = 0; else if ((*OpPtr)->digit == FPUCODE) fpucode = 0; exactMatch = 1; } } /* if (*codeptr == *(data + bytesMatched)) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -