- Timestamp:
- May 30, 2012 3:58:23 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/dis.h
r37702 r41501 751 751 /** @todo DISAnnotate(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, register reader, memory reader); */ 752 752 753 DISDECL(bool) DISFormatYasmIsOddEncoding(PDISCPUSTATE pCpu); 754 753 755 754 756 RT_C_DECLS_END -
trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp
r41495 r41501 1186 1186 } 1187 1187 1188 1189 /** 1190 * Checks if the encoding of the given disassembled instruction is something we 1191 * can never get YASM to produce. 1192 * 1193 * @returns true if it's odd, false if it isn't. 1194 * @param pCpu The disassembler output. The byte fetcher callback will 1195 * be used if present as we might need to fetch opcode 1196 * bytes. 1197 */ 1198 DISDECL(bool) DISFormatYasmIsOddEncoding(PDISCPUSTATE pCpu) 1199 { 1200 /* 1201 * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons. 1202 */ 1203 if ( pCpu->addrmode != CPUMODE_16BIT ///@todo correct? 1204 && pCpu->ModRM.Bits.Rm == 4 1205 && pCpu->ModRM.Bits.Mod != 3) 1206 { 1207 /* No scaled index SIB (index=4), except for ESP. */ 1208 if ( pCpu->SIB.Bits.Index == 4 1209 && pCpu->SIB.Bits.Base != 4) 1210 return true; 1211 1212 /* EBP + displacement */ 1213 if ( pCpu->ModRM.Bits.Mod != 0 1214 && pCpu->SIB.Bits.Base == 5 1215 && pCpu->SIB.Bits.Scale == 0) 1216 return true; 1217 } 1218 1219 /* 1220 * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf! 1221 */ 1222 if ( pCpu->pCurInstr->opcode == OP_SHL 1223 && pCpu->ModRM.Bits.Reg == 6) 1224 return true; 1225 1226 /* 1227 * Check for multiple prefixes of the same kind. 1228 */ 1229 uint32_t fPrefixes = 0; 1230 for (uint32_t offOpcode = 0; offOpcode < 32; offOpcode++) 1231 { 1232 uint32_t f; 1233 switch (DISReadByte(pCpu, offOpcode + pCpu->opaddr)) 1234 { 1235 case 0xf0: 1236 f = PREFIX_LOCK; 1237 break; 1238 1239 case 0xf2: 1240 case 0xf3: 1241 f = PREFIX_REP; /* yes, both */ 1242 break; 1243 1244 case 0x2e: 1245 case 0x3e: 1246 case 0x26: 1247 case 0x36: 1248 case 0x64: 1249 case 0x65: 1250 f = PREFIX_SEG; 1251 break; 1252 1253 case 0x66: 1254 f = PREFIX_OPSIZE; 1255 break; 1256 1257 case 0x67: 1258 f = PREFIX_ADDRSIZE; 1259 break; 1260 1261 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: 1262 case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: 1263 f = pCpu->mode == CPUMODE_64BIT ? PREFIX_REX : 0; 1264 break; 1265 1266 default: 1267 f = 0; 1268 break; 1269 } 1270 if (!f) 1271 break; /* done */ 1272 if (fPrefixes & f) 1273 return true; 1274 fPrefixes |= f; 1275 } 1276 1277 /* segment overrides are fun */ 1278 if (fPrefixes & PREFIX_SEG) 1279 { 1280 /* no effective address which it may apply to. */ 1281 Assert((pCpu->prefix & PREFIX_SEG) || pCpu->mode == CPUMODE_64BIT); 1282 if ( !DIS_IS_EFFECTIVE_ADDR(pCpu->param1.flags) 1283 && !DIS_IS_EFFECTIVE_ADDR(pCpu->param2.flags) 1284 && !DIS_IS_EFFECTIVE_ADDR(pCpu->param3.flags)) 1285 return true; 1286 } 1287 1288 /* fixed register + addr override doesn't go down all that well. */ 1289 if (fPrefixes & PREFIX_ADDRSIZE) 1290 { 1291 Assert(pCpu->prefix & PREFIX_ADDRSIZE); 1292 if ( pCpu->pCurInstr->param3 == OP_PARM_NONE 1293 && pCpu->pCurInstr->param2 == OP_PARM_NONE 1294 && ( pCpu->pCurInstr->param1 >= OP_PARM_REG_GEN32_START 1295 && pCpu->pCurInstr->param1 <= OP_PARM_REG_GEN32_END)) 1296 return true; 1297 } 1298 1299 /* Almost all prefixes are bad. */ 1300 if (fPrefixes) 1301 { 1302 switch (pCpu->pCurInstr->opcode) 1303 { 1304 /* nop w/ prefix(es). */ 1305 case OP_NOP: 1306 return true; 1307 1308 case OP_JMP: 1309 if ( pCpu->pCurInstr->param1 != OP_PARM_Jb 1310 && pCpu->pCurInstr->param1 != OP_PARM_Jv) 1311 break; 1312 /* fall thru */ 1313 case OP_JO: 1314 case OP_JNO: 1315 case OP_JC: 1316 case OP_JNC: 1317 case OP_JE: 1318 case OP_JNE: 1319 case OP_JBE: 1320 case OP_JNBE: 1321 case OP_JS: 1322 case OP_JNS: 1323 case OP_JP: 1324 case OP_JNP: 1325 case OP_JL: 1326 case OP_JNL: 1327 case OP_JLE: 1328 case OP_JNLE: 1329 /** @todo branch hinting 0x2e/0x3e... */ 1330 return true; 1331 } 1332 1333 } 1334 1335 /* All but the segment prefix is bad news. */ 1336 if (fPrefixes & ~PREFIX_SEG) 1337 { 1338 switch (pCpu->pCurInstr->opcode) 1339 { 1340 case OP_POP: 1341 case OP_PUSH: 1342 if ( pCpu->pCurInstr->param1 >= OP_PARM_REG_SEG_START 1343 && pCpu->pCurInstr->param1 <= OP_PARM_REG_SEG_END) 1344 return true; 1345 if ( (fPrefixes & ~PREFIX_OPSIZE) 1346 && pCpu->pCurInstr->param1 >= OP_PARM_REG_GEN32_START 1347 && pCpu->pCurInstr->param1 <= OP_PARM_REG_GEN32_END) 1348 return true; 1349 break; 1350 1351 case OP_POPA: 1352 case OP_POPF: 1353 case OP_PUSHA: 1354 case OP_PUSHF: 1355 if (fPrefixes & ~PREFIX_OPSIZE) 1356 return true; 1357 break; 1358 } 1359 } 1360 1361 /* Implicit 8-bit register instructions doesn't mix with operand size. */ 1362 if ( (fPrefixes & PREFIX_OPSIZE) 1363 && ( ( pCpu->pCurInstr->param1 == OP_PARM_Gb /* r8 */ 1364 && pCpu->pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */) 1365 || ( pCpu->pCurInstr->param2 == OP_PARM_Gb /* r8 */ 1366 && pCpu->pCurInstr->param1 == OP_PARM_Eb /* r8/mem8 */)) 1367 ) 1368 { 1369 switch (pCpu->pCurInstr->opcode) 1370 { 1371 case OP_ADD: 1372 case OP_OR: 1373 case OP_ADC: 1374 case OP_SBB: 1375 case OP_AND: 1376 case OP_SUB: 1377 case OP_XOR: 1378 case OP_CMP: 1379 return true; 1380 default: 1381 break; 1382 } 1383 } 1384 1385 1386 /* 1387 * Check for the version of xyz reg,reg instruction that the assembler doesn't use. 1388 * 1389 * For example: 1390 * expected: 1aee sbb ch, dh ; SBB r8, r/m8 1391 * yasm: 18F5 sbb ch, dh ; SBB r/m8, r8 1392 */ 1393 if (pCpu->ModRM.Bits.Mod == 3 /* reg,reg */) 1394 { 1395 switch (pCpu->pCurInstr->opcode) 1396 { 1397 case OP_ADD: 1398 case OP_OR: 1399 case OP_ADC: 1400 case OP_SBB: 1401 case OP_AND: 1402 case OP_SUB: 1403 case OP_XOR: 1404 case OP_CMP: 1405 if ( ( pCpu->pCurInstr->param1 == OP_PARM_Gb /* r8 */ 1406 && pCpu->pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */) 1407 || ( pCpu->pCurInstr->param1 == OP_PARM_Gv /* rX */ 1408 && pCpu->pCurInstr->param2 == OP_PARM_Ev /* rX/memX */)) 1409 return true; 1410 1411 /* 82 (see table A-6). */ 1412 if (pCpu->opcode == 0x82) 1413 return true; 1414 break; 1415 1416 /* ff /0, fe /0, ff /1, fe /0 */ 1417 case OP_DEC: 1418 case OP_INC: 1419 return true; 1420 1421 case OP_POP: 1422 case OP_PUSH: 1423 Assert(pCpu->opcode == 0x8f); 1424 return true; 1425 1426 default: 1427 break; 1428 } 1429 } 1430 1431 /* shl eax,1 will be assembled to the form without the immediate byte. */ 1432 if ( pCpu->pCurInstr->param2 == OP_PARM_Ib 1433 && (uint8_t)pCpu->param2.parval == 1) 1434 { 1435 switch (pCpu->pCurInstr->opcode) 1436 { 1437 case OP_SHL: 1438 case OP_SHR: 1439 case OP_SAR: 1440 case OP_RCL: 1441 case OP_RCR: 1442 case OP_ROL: 1443 case OP_ROR: 1444 return true; 1445 } 1446 } 1447 1448 /* And some more - see table A-6. */ 1449 if (pCpu->opcode == 0x82) 1450 { 1451 switch (pCpu->pCurInstr->opcode) 1452 { 1453 case OP_ADD: 1454 case OP_OR: 1455 case OP_ADC: 1456 case OP_SBB: 1457 case OP_AND: 1458 case OP_SUB: 1459 case OP_XOR: 1460 case OP_CMP: 1461 return true; 1462 break; 1463 } 1464 } 1465 1466 1467 /* check for REX.X = 1 without SIB. */ 1468 1469 /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual 1470 says (intel doesn't appear to care). */ 1471 switch (pCpu->pCurInstr->opcode) 1472 { 1473 case OP_SETO: 1474 case OP_SETNO: 1475 case OP_SETC: 1476 case OP_SETNC: 1477 case OP_SETE: 1478 case OP_SETNE: 1479 case OP_SETBE: 1480 case OP_SETNBE: 1481 case OP_SETS: 1482 case OP_SETNS: 1483 case OP_SETP: 1484 case OP_SETNP: 1485 case OP_SETL: 1486 case OP_SETNL: 1487 case OP_SETLE: 1488 case OP_SETNLE: 1489 AssertMsg(pCpu->opcode >= 0x90 && pCpu->opcode <= 0x9f, ("%#x\n", pCpu->opcode)); 1490 if (pCpu->ModRM.Bits.Reg != 2) 1491 return true; 1492 break; 1493 } 1494 1495 /* 1496 * The MOVZX reg32,mem16 instruction without an operand size prefix 1497 * doesn't quite make sense... 1498 */ 1499 if ( pCpu->pCurInstr->opcode == OP_MOVZX 1500 && pCpu->opcode == 0xB7 1501 && (pCpu->mode == CPUMODE_16BIT) != !!(fPrefixes & PREFIX_OPSIZE)) 1502 return true; 1503 1504 return false; 1505 } 1506 -
trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
r38636 r41501 108 108 109 109 /** 110 * Checks if the encoding of the current instruction is something111 * we can never get the assembler to produce.112 *113 * @returns true if it's odd, false if it isn't.114 * @param pCpu The disassembler output.115 */116 static bool MyDisasYasmFormatterIsOddEncoding(PMYDISSTATE pState)117 {118 /*119 * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.120 */121 if ( pState->Cpu.addrmode != CPUMODE_16BIT ///@todo correct?122 && pState->Cpu.ModRM.Bits.Rm == 4123 && pState->Cpu.ModRM.Bits.Mod != 3)124 {125 /* No scaled index SIB (index=4), except for ESP. */126 if ( pState->Cpu.SIB.Bits.Index == 4127 && pState->Cpu.SIB.Bits.Base != 4)128 return true;129 130 /* EBP + displacement */131 if ( pState->Cpu.ModRM.Bits.Mod != 0132 && pState->Cpu.SIB.Bits.Base == 5133 && pState->Cpu.SIB.Bits.Scale == 0)134 return true;135 }136 137 /*138 * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!139 */140 if ( pState->Cpu.pCurInstr->opcode == OP_SHL141 && pState->Cpu.ModRM.Bits.Reg == 6)142 return true;143 144 /*145 * Check for multiple prefixes of the same kind.146 */147 uint32_t fPrefixes = 0;148 for (uint8_t const *pu8 = pState->pbInstr;; pu8++)149 {150 uint32_t f;151 switch (*pu8)152 {153 case 0xf0:154 f = PREFIX_LOCK;155 break;156 157 case 0xf2:158 case 0xf3:159 f = PREFIX_REP; /* yes, both */160 break;161 162 case 0x2e:163 case 0x3e:164 case 0x26:165 case 0x36:166 case 0x64:167 case 0x65:168 f = PREFIX_SEG;169 break;170 171 case 0x66:172 f = PREFIX_OPSIZE;173 break;174 175 case 0x67:176 f = PREFIX_ADDRSIZE;177 break;178 179 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:180 case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:181 f = pState->Cpu.mode == CPUMODE_64BIT ? PREFIX_REX : 0;182 break;183 184 default:185 f = 0;186 break;187 }188 if (!f)189 break; /* done */190 if (fPrefixes & f)191 return true;192 fPrefixes |= f;193 }194 195 /* segment overrides are fun */196 if (fPrefixes & PREFIX_SEG)197 {198 /* no effective address which it may apply to. */199 Assert((pState->Cpu.prefix & PREFIX_SEG) || pState->Cpu.mode == CPUMODE_64BIT);200 if ( !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param1.flags)201 && !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param2.flags)202 && !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param3.flags))203 return true;204 }205 206 /* fixed register + addr override doesn't go down all that well. */207 if (fPrefixes & PREFIX_ADDRSIZE)208 {209 Assert(pState->Cpu.prefix & PREFIX_ADDRSIZE);210 if ( pState->Cpu.pCurInstr->param3 == OP_PARM_NONE211 && pState->Cpu.pCurInstr->param2 == OP_PARM_NONE212 && ( pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START213 && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END))214 return true;215 }216 217 /* Almost all prefixes are bad. */218 if (fPrefixes)219 {220 switch (pState->Cpu.pCurInstr->opcode)221 {222 /* nop w/ prefix(es). */223 case OP_NOP:224 return true;225 226 case OP_JMP:227 if ( pState->Cpu.pCurInstr->param1 != OP_PARM_Jb228 && pState->Cpu.pCurInstr->param1 != OP_PARM_Jv)229 break;230 /* fall thru */231 case OP_JO:232 case OP_JNO:233 case OP_JC:234 case OP_JNC:235 case OP_JE:236 case OP_JNE:237 case OP_JBE:238 case OP_JNBE:239 case OP_JS:240 case OP_JNS:241 case OP_JP:242 case OP_JNP:243 case OP_JL:244 case OP_JNL:245 case OP_JLE:246 case OP_JNLE:247 /** @todo branch hinting 0x2e/0x3e... */248 return true;249 }250 251 }252 253 /* All but the segment prefix is bad news. */254 if (fPrefixes & ~PREFIX_SEG)255 {256 switch (pState->Cpu.pCurInstr->opcode)257 {258 case OP_POP:259 case OP_PUSH:260 if ( pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_SEG_START261 && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_SEG_END)262 return true;263 if ( (fPrefixes & ~PREFIX_OPSIZE)264 && pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START265 && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END)266 return true;267 break;268 269 case OP_POPA:270 case OP_POPF:271 case OP_PUSHA:272 case OP_PUSHF:273 if (fPrefixes & ~PREFIX_OPSIZE)274 return true;275 break;276 }277 }278 279 /* Implicit 8-bit register instructions doesn't mix with operand size. */280 if ( (fPrefixes & PREFIX_OPSIZE)281 && ( ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */282 && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)283 || ( pState->Cpu.pCurInstr->param2 == OP_PARM_Gb /* r8 */284 && pState->Cpu.pCurInstr->param1 == OP_PARM_Eb /* r8/mem8 */))285 )286 {287 switch (pState->Cpu.pCurInstr->opcode)288 {289 case OP_ADD:290 case OP_OR:291 case OP_ADC:292 case OP_SBB:293 case OP_AND:294 case OP_SUB:295 case OP_XOR:296 case OP_CMP:297 return true;298 default:299 break;300 }301 }302 303 304 /*305 * Check for the version of xyz reg,reg instruction that the assembler doesn't use.306 *307 * For example:308 * expected: 1aee sbb ch, dh ; SBB r8, r/m8309 * yasm: 18F5 sbb ch, dh ; SBB r/m8, r8310 */311 if (pState->Cpu.ModRM.Bits.Mod == 3 /* reg,reg */)312 {313 switch (pState->Cpu.pCurInstr->opcode)314 {315 case OP_ADD:316 case OP_OR:317 case OP_ADC:318 case OP_SBB:319 case OP_AND:320 case OP_SUB:321 case OP_XOR:322 case OP_CMP:323 if ( ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */324 && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)325 || ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gv /* rX */326 && pState->Cpu.pCurInstr->param2 == OP_PARM_Ev /* rX/memX */))327 return true;328 329 /* 82 (see table A-6). */330 if (pState->Cpu.opcode == 0x82)331 return true;332 break;333 334 /* ff /0, fe /0, ff /1, fe /0 */335 case OP_DEC:336 case OP_INC:337 return true;338 339 case OP_POP:340 case OP_PUSH:341 Assert(pState->Cpu.opcode == 0x8f);342 return true;343 344 default:345 break;346 }347 }348 349 /* shl eax,1 will be assembled to the form without the immediate byte. */350 if ( pState->Cpu.pCurInstr->param2 == OP_PARM_Ib351 && (uint8_t)pState->Cpu.param2.parval == 1)352 {353 switch (pState->Cpu.pCurInstr->opcode)354 {355 case OP_SHL:356 case OP_SHR:357 case OP_SAR:358 case OP_RCL:359 case OP_RCR:360 case OP_ROL:361 case OP_ROR:362 return true;363 }364 }365 366 /* And some more - see table A-6. */367 if (pState->Cpu.opcode == 0x82)368 {369 switch (pState->Cpu.pCurInstr->opcode)370 {371 case OP_ADD:372 case OP_OR:373 case OP_ADC:374 case OP_SBB:375 case OP_AND:376 case OP_SUB:377 case OP_XOR:378 case OP_CMP:379 return true;380 break;381 }382 }383 384 385 /* check for REX.X = 1 without SIB. */386 387 /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual388 says (intel doesn't appear to care). */389 switch (pState->Cpu.pCurInstr->opcode)390 {391 case OP_SETO:392 case OP_SETNO:393 case OP_SETC:394 case OP_SETNC:395 case OP_SETE:396 case OP_SETNE:397 case OP_SETBE:398 case OP_SETNBE:399 case OP_SETS:400 case OP_SETNS:401 case OP_SETP:402 case OP_SETNP:403 case OP_SETL:404 case OP_SETNL:405 case OP_SETLE:406 case OP_SETNLE:407 AssertMsg(pState->Cpu.opcode >= 0x90 && pState->Cpu.opcode <= 0x9f, ("%#x\n", pState->Cpu.opcode));408 if (pState->Cpu.ModRM.Bits.Reg != 2)409 return true;410 break;411 }412 413 /*414 * The MOVZX reg32,mem16 instruction without an operand size prefix415 * doesn't quite make sense...416 */417 if ( pState->Cpu.pCurInstr->opcode == OP_MOVZX418 && pState->Cpu.opcode == 0xB7419 && (pState->Cpu.mode == CPUMODE_16BIT) != !!(fPrefixes & PREFIX_OPSIZE))420 return true;421 422 return false;423 }424 425 426 /**427 110 * Masm style. 428 111 * … … 689 372 /* Use db for odd encodings that we can't make the assembler use. */ 690 373 if ( State.enmUndefOp == kUndefOp_DefineByte 691 && MyDisasYasmFormatterIsOddEncoding(&State))374 && DISFormatYasmIsOddEncoding(&State.Cpu)) 692 375 { 693 376 RTPrintf(" db");
Note:
See TracChangeset
for help on using the changeset viewer.