summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disasm.c82
-rw-r--r--disasm.h2
-rw-r--r--ndisasm.c9
3 files changed, 86 insertions, 7 deletions
diff --git a/disasm.c b/disasm.c
index 63fd37b..f410418 100644
--- a/disasm.c
+++ b/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;
}
diff --git a/disasm.h b/disasm.h
index 56785ce..6467730 100644
--- a/disasm.h
+++ b/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
diff --git a/ndisasm.c b/ndisasm.c
index 766119b..75fc325 100644
--- a/ndisasm.c
+++ b/ndisasm.c
@@ -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;