mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-15 09:09:58 +08:00
disasm: when no instruction is found, consider a naked prefix
If we can't find a matching instruction, rather than printing it as a "db" literal, consider first if we can disassemble it as a naked prefix.
This commit is contained in:
parent
d1174fb1a6
commit
ed37aa8070
82
disasm.c
82
disasm.c
@ -1420,8 +1420,86 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
|
||||
return length;
|
||||
}
|
||||
|
||||
int32_t eatbyte(uint8_t *data, char *output, int outbufsize)
|
||||
/*
|
||||
* This is called when we don't have a complete instruction. If it
|
||||
* is a standalone *single-byte* prefix show it as such, otherwise
|
||||
* print it as a literal.
|
||||
*/
|
||||
int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize)
|
||||
{
|
||||
snprintf(output, outbufsize, "db 0x%02X", *data);
|
||||
uint8_t byte = *data;
|
||||
const char *str = NULL;
|
||||
|
||||
switch (byte) {
|
||||
case 0xF2:
|
||||
str = "rep";
|
||||
break;
|
||||
case 0xF3:
|
||||
str = "repne";
|
||||
break;
|
||||
case 0x9B:
|
||||
str = "wait";
|
||||
break;
|
||||
case 0xF0:
|
||||
str = "lock";
|
||||
break;
|
||||
case 0x2E:
|
||||
str = "cs";
|
||||
break;
|
||||
case 0x36:
|
||||
str = "ss";
|
||||
break;
|
||||
case 0x3E:
|
||||
str = "ss";
|
||||
break;
|
||||
case 0x26:
|
||||
str = "es";
|
||||
break;
|
||||
case 0x64:
|
||||
str = "fs";
|
||||
break;
|
||||
case 0x65:
|
||||
str = "gs";
|
||||
break;
|
||||
case 0x66:
|
||||
str = (segsize == 16) ? "o32" : "o16";
|
||||
break;
|
||||
case 0x67:
|
||||
str = (segsize == 32) ? "a16" : "a32";
|
||||
break;
|
||||
case REX_P + 0x0:
|
||||
case REX_P + 0x1:
|
||||
case REX_P + 0x2:
|
||||
case REX_P + 0x3:
|
||||
case REX_P + 0x4:
|
||||
case REX_P + 0x5:
|
||||
case REX_P + 0x6:
|
||||
case REX_P + 0x7:
|
||||
case REX_P + 0x8:
|
||||
case REX_P + 0x9:
|
||||
case REX_P + 0xA:
|
||||
case REX_P + 0xB:
|
||||
case REX_P + 0xC:
|
||||
case REX_P + 0xD:
|
||||
case REX_P + 0xE:
|
||||
case REX_P + 0xF:
|
||||
if (segsize == 64) {
|
||||
snprintf(output, outbufsize, "rex%s%s%s%s%s",
|
||||
(byte == REX_P) ? "" : ".",
|
||||
(byte & REX_W) ? "w" : "",
|
||||
(byte & REX_R) ? "r" : "",
|
||||
(byte & REX_X) ? "x" : "",
|
||||
(byte & REX_B) ? "b" : "");
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
default:
|
||||
snprintf(output, outbufsize, "db 0x%02x", byte);
|
||||
break;
|
||||
}
|
||||
|
||||
if (str)
|
||||
strcpy(output, str);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
2
disasm.h
2
disasm.h
@ -13,6 +13,6 @@
|
||||
|
||||
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
|
||||
int32_t offset, int autosync, uint32_t prefer);
|
||||
int32_t eatbyte(uint8_t *data, char *output, int outbufsize);
|
||||
int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize);
|
||||
|
||||
#endif
|
||||
|
@ -273,7 +273,8 @@ int main(int argc, char **argv)
|
||||
if ((nextsync || synclen) &&
|
||||
(uint32_t)offset == nextsync) {
|
||||
if (synclen) {
|
||||
fprintf(stdout, "%08"PRIX32" skipping 0x%"PRIX32" bytes\n", offset, synclen);
|
||||
fprintf(stdout, "%08"PRIX32" skipping 0x%"PRIX32" bytes\n",
|
||||
offset, synclen);
|
||||
offset += synclen;
|
||||
skip(synclen, fp);
|
||||
}
|
||||
@ -282,12 +283,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
while (p > q && (p - q >= INSN_MAX || lenread == 0)) {
|
||||
lendis =
|
||||
disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits, offset, autosync,
|
||||
prefer);
|
||||
disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits,
|
||||
offset, autosync, prefer);
|
||||
if (!lendis || lendis > (p - q)
|
||||
|| ((nextsync || synclen) &&
|
||||
(uint32_t)lendis > nextsync - offset))
|
||||
lendis = eatbyte((uint8_t *) q, outbuf, sizeof(outbuf));
|
||||
lendis = eatbyte((uint8_t *) q, outbuf, sizeof(outbuf), bits);
|
||||
output_ins(offset, (uint8_t *) q, lendis, outbuf);
|
||||
q += lendis;
|
||||
offset += lendis;
|
||||
|
Loading…
Reference in New Issue
Block a user