📄 disasm-x86.c
字号:
else if (*(codeptr + 1) == '\0') { /* * We failed to match a byte against 'data' however this * is the very last byte of the opcode, so it may have * been modified by adding an integer between 0-7 in the * case of +rb/+rw/+rd/+i opcodes - check if this is the * case. */ if ((*OpPtr)->digit == REGCODE) { /* * If the 'digit' field of OpPtr is REGCODE *and* this * is the last byte of the opcode, it is possible that * the byte stored in 'data' is up to 7 numbers larger * than the opcode stored in OpPtr. This means that * the difference between the 'data' byte and the 'OpPtr' * byte is a special value corresponding to a specific * register. These registers are listed in Table 3.1 of * the Intel Instruction Set Reference. If we indeed find * the difference to be a number between 0 and 7, store * it into 'tmpreg' for future reference. */ regcode = (unsigned char) *(data + bytesMatched) - (unsigned char) *codeptr; if ((regcode >= 0) && (regcode <= 7)) { /* * We have just found a good match on the last byte * of the opcode - therefore the data string matches * the stored opcode byte for byte - it is an exact * match */ ++bytesMatched; exactMatch = 1; } else { /* * regcode is larger than 8, so this opcode does not * satisfy the +rb/+rw/+rd nomenclature - reset * regcode and BytesMatched. */ regcode = (-1); bytesMatched = 0; break; } } /* if ((*OpPtr)->digit == REGCODE) */ else if ((*OpPtr)->digit == FPUCODE) { /* * Since this is the last byte of the opcode, and since * 'digit' is FPUCODE, this last byte of the opcode may * have been altered by adding a number from 0-7, in * order to reflect an fpu stack register. Figure out * what the difference is, and assign it to tmpfpu for * later use. */ fpucode = (unsigned char) *(data + bytesMatched) - (unsigned char) *codeptr; if ((fpucode >= 0) && (fpucode <= 7)) { ++bytesMatched; exactMatch = 1; } else { /* * fpucode is larger than 8, and so it cannot represent * a fpu stack register - reset fpucode and bytesMatched. */ fpucode = (-1); bytesMatched = 0; break; } } /* if ((*OpPtr)->digit == FPUCODE) */ } /* if (*(codeptr + 1) == '\0') */ else { /* * We failed to match an opcode byte against 'data' and it * is not the last byte of the opcode, so this is not a * good match */ bytesMatched = 0; break; } } /* while (*++codeptr) */ if (bytesMatched < (*OpPtr)->oplen) { /* * We did not match all of the necessary bytes - bad match */ continue; } /* * If the opcode is expecting a register code * and we do not have one, it is a bad match. The only * case I can think of in which this will happen is with * NOP and XCHG and we get a "66 90" to indicate * a 32 bit version of NOP. Since there is technically no * 32 bit version of NOP, we would normally move onto * XCHG (where there is a 32 bit version) and use it, but * we do not want to do that since 0x90 is specifically * NOP. */ if ((regcode == (-1)) && ((*OpPtr)->digit == REGCODE)) continue; if ((fpucode == (-1)) && ((*OpPtr)->digit == FPUCODE)) continue; /* * If the current prospective match expects a ModR/M (and SIB) * byte, make sure that the corresponding byte(s) in our actual * data string matches up with the correct columns in * the ModR/M (and SIB) tables given in tables 2-1, 2-2, and 2-3 * of the Intel Architecture Software Developers Manual, Vol 2. */ if ((((*OpPtr)->digit >= 0) && ((*OpPtr)->digit <= 7)) || ((*OpPtr)->digit == REGRM)) { int ret; ret = x86processModSib(ws, data + bytesMatched, *OpPtr, &msinfo); if (ret < 0) continue; /* bad match */ assert(msinfo.modptr != 0); bytesMatched += ret; } /* * Our opcode passed all of the tests, add it to our array * of possible matches - there may be more than one instruction * which matches the opcode, so we will store all matches and * sort it out later. One example is NOP and XCHG ax,ax both * of which have an opcode of 0x90. They both do the same thing, * but from our viewpoint, we would rather pick NOP as the final * instruction instead of XCHG ax,ax. */ matches[midx].bytesMatched = bytesMatched; matches[midx].opPtr = *OpPtr; matches[midx].regcode = regcode; matches[midx].fpucode = fpucode; matches[midx].prefixPriority = 0; matches[midx].msinfo = msinfo; ++midx; if (midx >= MAXBUF) { sprintf(outbuf, "x86findOpCode: error: too many matches (>= %d)", MAXBUF); return (0); } } /* for (OpPtr = candidates; *OpPtr; ++OpPtr) */#if 0 printf("x86findOpCode: number of matches: %d\n", midx);#endif /* * We now have a prospective list of matches, contained in the * array 'matches'. Each of these matches shares their opcode * with the opcode we are trying to disassemble, and also passed * a few sanity tests. There are two tests left to perform: * * 1. Prefix overrides: if there is an operand override then we * may have stored both the 16 and 32 bit versions of the * same instruction in our array 'matches'. In this case * we need to pick out the right one depending upon what * mode we are in (16 or 32 bit mode). This test could be * done in the main loop above, but it would be extremely * messy since we may hit the 16 bit version before the 32 * bit version and there would be some ugliness to figure out * to throw one of them away. In the interests of elegance, * I put this test after the main loop. * 2. If we are in 16 bit mode, and our potential match is marked * as expecting 32 bits with no operands (example: INSD, IRETD). * In this case, reject the potential match. */ foundBestMatch = 0; for (ii = 0; ii < midx; ++ii) { pret = x86testPrefix(ws, matches[ii].opPtr); if (pret == 0) continue; if (foundBestMatch) { /* * If we have already found a match, we need * to check if this match is better than * the previous match. */ betterMatch = 0; /* * Check if the prefix is a better match for this * instruction */ if (pret > bestmatch->prefixPriority) betterMatch = 1; /* * This test is for the case of FADD. If we have two * matches, where one uses a ModR/M byte and the other * is defined with +rb/+rw/+rd/+i, then the latter is * chosen over the former. With FADD, there are two * separate opcodes (D8 /0 and D8 C0 +i). C0 is in column * 0, so it is possible to match D8 C0 against the wrong * opcode with the ModR/M. */ if (x86UsesRegFPU(matches[ii].opPtr) && x86UsesModRM(bestmatch->opPtr)) { betterMatch = 1; } else if (x86UsesRegFPU(bestmatch->opPtr) && x86UsesModRM(matches[ii].opPtr)) { betterMatch = 0; continue; } else if (!x86UsesModRM(matches[ii].opPtr) && x86UsesModRM(bestmatch->opPtr)) { /* * If the previous match uses a ModR/M byte and the * current match does not, then the current match is * a better match. An example of this is FTST and * FLDENV. FTST is D9 E4, and FLDENV is D9 /4. E4 is * in column 4, so we must make sure we choose FTST * over FLDENV. */ betterMatch = 1; } if (betterMatch) { matches[ii].prefixPriority = pret; *bestmatch = matches[ii]; } } /* if (foundBestMatch) */ else { /* * We have not yet found a match, and this one passed * the prefix requirements so record it. */ matches[ii].prefixPriority = pret; *bestmatch = matches[ii]; foundBestMatch = 1; } } if (foundBestMatch) return (bestmatch->bytesMatched + (long) prefBytes); else return (0);} /* x86findOpCode() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -