mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-11-27 08:10:07 +08:00
Fixes for 64-bit ndisasm.
This fixes some of the most glaring bugs in ndisasm 64-bit mode. We're still getting redundant prefixes for unknown reason, however.
This commit is contained in:
parent
88aa185d36
commit
b061d595fb
@ -25,8 +25,9 @@
|
|||||||
* assembly mode or the operand-size override on the operand
|
* assembly mode or the operand-size override on the operand
|
||||||
* \37 - a word constant, from the _segment_ part of operand 0
|
* \37 - a word constant, from the _segment_ part of operand 0
|
||||||
* \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
|
* \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
|
||||||
* \44, \45, \46 - select between \3[012] and \4[012] depending on 16/32 bit
|
* \44, \45, \46 - select between \3[012], \4[012] and \5[456]
|
||||||
* assembly mode or the address-size override on the operand
|
* depending on assembly mode or the address-size override
|
||||||
|
* on the operand.
|
||||||
* \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
|
* \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
|
||||||
* \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
|
* \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
|
||||||
* \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
|
* \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
|
||||||
|
134
disasm.c
134
disasm.c
@ -122,6 +122,8 @@ static int whichreg(int32_t regflags, int regval, int rex)
|
|||||||
return rd_reg16[regval];
|
return rd_reg16[regval];
|
||||||
if (!((REGMEM | BITS32) & ~regflags))
|
if (!((REGMEM | BITS32) & ~regflags))
|
||||||
return rd_reg32[regval];
|
return rd_reg32[regval];
|
||||||
|
if (!((REGMEM | BITS64) & ~regflags))
|
||||||
|
return rd_reg64[regval];
|
||||||
if (!(REG_SREG & ~regflags))
|
if (!(REG_SREG & ~regflags))
|
||||||
return rd_sreg[regval & 7]; /* Ignore REX */
|
return rd_sreg[regval & 7]; /* Ignore REX */
|
||||||
if (!(REG_CREG & ~regflags))
|
if (!(REG_CREG & ~regflags))
|
||||||
@ -338,12 +340,13 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
|
|
||||||
while (*r) {
|
while (*r) {
|
||||||
int c = *r++;
|
int c = *r++;
|
||||||
if (c >= 01 && c <= 03) {
|
|
||||||
|
/* FIX: change this into a switch */
|
||||||
|
if (c >= 01 && c <= 03) {
|
||||||
while (c--)
|
while (c--)
|
||||||
if (*r++ != *data++)
|
if (*r++ != *data++)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
} else if (c == 04) {
|
||||||
if (c == 04) {
|
|
||||||
switch (*data++) {
|
switch (*data++) {
|
||||||
case 0x07:
|
case 0x07:
|
||||||
ins->oprs[0].basereg = 0;
|
ins->oprs[0].basereg = 0;
|
||||||
@ -357,8 +360,7 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
} else if (c == 05) {
|
||||||
if (c == 05) {
|
|
||||||
switch (*data++) {
|
switch (*data++) {
|
||||||
case 0xA1:
|
case 0xA1:
|
||||||
ins->oprs[0].basereg = 4;
|
ins->oprs[0].basereg = 4;
|
||||||
@ -368,9 +370,8 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
} else if (c == 06) {
|
||||||
if (c == 06) {
|
|
||||||
switch (*data++) {
|
switch (*data++) {
|
||||||
case 0x06:
|
case 0x06:
|
||||||
ins->oprs[0].basereg = 0;
|
ins->oprs[0].basereg = 0;
|
||||||
@ -387,8 +388,7 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
} else if (c == 07) {
|
||||||
if (c == 07) {
|
|
||||||
switch (*data++) {
|
switch (*data++) {
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
ins->oprs[0].basereg = 4;
|
ins->oprs[0].basereg = 4;
|
||||||
@ -399,32 +399,28 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
} else if (c >= 010 && c <= 012) {
|
||||||
if (c >= 010 && c <= 012) {
|
|
||||||
int t = *r++, d = *data++;
|
int t = *r++, d = *data++;
|
||||||
if (d < t || d > t + 7)
|
if (d < t || d > t + 7)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else {
|
else {
|
||||||
ins->oprs[c - 010].basereg = d - t;
|
ins->oprs[c - 010].basereg = (d-t)+(rex & REX_B ? 8 : 0);
|
||||||
ins->oprs[c - 010].segment |= SEG_RMREG;
|
ins->oprs[c - 010].segment |= SEG_RMREG;
|
||||||
}
|
}
|
||||||
}
|
} else if (c == 017) {
|
||||||
if (c == 017)
|
|
||||||
if (*data++)
|
if (*data++)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (c >= 014 && c <= 016) {
|
} else if (c >= 014 && c <= 016) {
|
||||||
ins->oprs[c - 014].offset = (int8_t)*data++;
|
ins->oprs[c - 014].offset = (int8_t)*data++;
|
||||||
ins->oprs[c - 014].segment |= SEG_SIGNED;
|
ins->oprs[c - 014].segment |= SEG_SIGNED;
|
||||||
}
|
} else if (c >= 020 && c <= 022) {
|
||||||
if (c >= 020 && c <= 022)
|
|
||||||
ins->oprs[c - 020].offset = *data++;
|
ins->oprs[c - 020].offset = *data++;
|
||||||
if (c >= 024 && c <= 026)
|
} else if (c >= 024 && c <= 026) {
|
||||||
ins->oprs[c - 024].offset = *data++;
|
ins->oprs[c - 024].offset = *data++;
|
||||||
if (c >= 030 && c <= 032) {
|
} else if (c >= 030 && c <= 032) {
|
||||||
ins->oprs[c - 030].offset = getu16(data);
|
ins->oprs[c - 030].offset = getu16(data);
|
||||||
data += 2;
|
data += 2;
|
||||||
}
|
} else if (c >= 034 && c <= 036) {
|
||||||
if (c >= 034 && c <= 036) {
|
|
||||||
if (osize == 32) {
|
if (osize == 32) {
|
||||||
ins->oprs[c - 034].offset = getu32(data);
|
ins->oprs[c - 034].offset = getu32(data);
|
||||||
data += 4;
|
data += 4;
|
||||||
@ -434,38 +430,38 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
}
|
}
|
||||||
if (segsize != asize)
|
if (segsize != asize)
|
||||||
ins->oprs[c - 034].addr_size = asize;
|
ins->oprs[c - 034].addr_size = asize;
|
||||||
}
|
} else if (c >= 040 && c <= 042) {
|
||||||
if (c >= 040 && c <= 042) {
|
|
||||||
ins->oprs[c - 040].offset = getu32(data);
|
ins->oprs[c - 040].offset = getu32(data);
|
||||||
data += 4;
|
data += 4;
|
||||||
}
|
} else if (c >= 044 && c <= 046) {
|
||||||
if (c >= 044 && c <= 046) {
|
switch (asize) {
|
||||||
/* hpa: should this be gets32/gets16? */
|
case 16:
|
||||||
if (asize == 32) {
|
|
||||||
ins->oprs[c - 044].offset = getu32(data);
|
|
||||||
data += 4;
|
|
||||||
} else {
|
|
||||||
ins->oprs[c - 044].offset = getu16(data);
|
ins->oprs[c - 044].offset = getu16(data);
|
||||||
data += 2;
|
data += 2;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
ins->oprs[c - 044].offset = getu32(data);
|
||||||
|
data += 4;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
ins->oprs[c - 044].offset = getu64(data);
|
||||||
|
data += 8;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (segsize != asize)
|
if (segsize != asize)
|
||||||
ins->oprs[c - 044].addr_size = asize;
|
ins->oprs[c - 044].addr_size = asize;
|
||||||
}
|
} else if (c >= 050 && c <= 052) {
|
||||||
if (c >= 050 && c <= 052) {
|
|
||||||
ins->oprs[c - 050].offset = gets8(data++);
|
ins->oprs[c - 050].offset = gets8(data++);
|
||||||
ins->oprs[c - 050].segment |= SEG_RELATIVE;
|
ins->oprs[c - 050].segment |= SEG_RELATIVE;
|
||||||
}
|
} else if (c >= 054 && c <= 056) {
|
||||||
if (c >= 054 && c <= 056) {
|
|
||||||
ins->oprs[c - 054].offset = getu64(data);
|
ins->oprs[c - 054].offset = getu64(data);
|
||||||
data += 8;
|
data += 8;
|
||||||
}
|
} else if (c >= 060 && c <= 062) {
|
||||||
if (c >= 060 && c <= 062) {
|
|
||||||
ins->oprs[c - 060].offset = gets16(data);
|
ins->oprs[c - 060].offset = gets16(data);
|
||||||
data += 2;
|
data += 2;
|
||||||
ins->oprs[c - 060].segment |= SEG_RELATIVE;
|
ins->oprs[c - 060].segment |= SEG_RELATIVE;
|
||||||
ins->oprs[c - 060].segment &= ~SEG_32BIT;
|
ins->oprs[c - 060].segment &= ~SEG_32BIT;
|
||||||
}
|
} else if (c >= 064 && c <= 066) {
|
||||||
if (c >= 064 && c <= 066) {
|
|
||||||
if (osize == 32) {
|
if (osize == 32) {
|
||||||
ins->oprs[c - 064].offset = getu32(data);
|
ins->oprs[c - 064].offset = getu32(data);
|
||||||
data += 4;
|
data += 4;
|
||||||
@ -480,101 +476,83 @@ static int matches(struct itemplate *t, uint8_t *data, int asize,
|
|||||||
(ins->oprs[c - 064].type & NON_SIZE)
|
(ins->oprs[c - 064].type & NON_SIZE)
|
||||||
| ((osize == 16) ? BITS16 : BITS32);
|
| ((osize == 16) ? BITS16 : BITS32);
|
||||||
}
|
}
|
||||||
}
|
} else if (c >= 070 && c <= 072) {
|
||||||
if (c >= 070 && c <= 072) {
|
|
||||||
ins->oprs[c - 070].offset = getu32(data);
|
ins->oprs[c - 070].offset = getu32(data);
|
||||||
data += 4;
|
data += 4;
|
||||||
ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
|
ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
|
||||||
}
|
} else if (c >= 0100 && c < 0130) {
|
||||||
if (c >= 0100 && c < 0130) {
|
|
||||||
int modrm = *data++;
|
int modrm = *data++;
|
||||||
ins->oprs[c & 07].basereg = (modrm >> 3) & 07;
|
ins->oprs[c & 07].basereg = ((modrm >> 3)&7)+(rex & REX_R ? 8 : 0);
|
||||||
ins->oprs[c & 07].segment |= SEG_RMREG;
|
ins->oprs[c & 07].segment |= SEG_RMREG;
|
||||||
data = do_ea(data, modrm, asize, segsize,
|
data = do_ea(data, modrm, asize, segsize,
|
||||||
&ins->oprs[(c >> 3) & 07], rex);
|
&ins->oprs[(c >> 3) & 07], rex);
|
||||||
}
|
} else if (c >= 0130 && c <= 0132) {
|
||||||
if (c >= 0130 && c <= 0132) {
|
|
||||||
ins->oprs[c - 0130].offset = getu16(data);
|
ins->oprs[c - 0130].offset = getu16(data);
|
||||||
data += 2;
|
data += 2;
|
||||||
}
|
} else if (c >= 0140 && c <= 0142) {
|
||||||
if (c >= 0140 && c <= 0142) {
|
|
||||||
ins->oprs[c - 0140].offset = getu32(data);
|
ins->oprs[c - 0140].offset = getu32(data);
|
||||||
data += 4;
|
data += 4;
|
||||||
}
|
} else if (c >= 0200 && c <= 0277) {
|
||||||
if (c >= 0200 && c <= 0277) {
|
|
||||||
int modrm = *data++;
|
int modrm = *data++;
|
||||||
if (((modrm >> 3) & 07) != (c & 07))
|
if (((modrm >> 3) & 07) != (c & 07))
|
||||||
return FALSE; /* spare field doesn't match up */
|
return FALSE; /* spare field doesn't match up */
|
||||||
data = do_ea(data, modrm, asize, segsize,
|
data = do_ea(data, modrm, asize, segsize,
|
||||||
&ins->oprs[(c >> 3) & 07], rex);
|
&ins->oprs[(c >> 3) & 07], rex);
|
||||||
}
|
} else if (c >= 0300 && c <= 0302) {
|
||||||
if (c >= 0300 && c <= 0302) {
|
|
||||||
if (asize)
|
if (asize)
|
||||||
ins->oprs[c - 0300].segment |= SEG_32BIT;
|
ins->oprs[c - 0300].segment |= SEG_32BIT;
|
||||||
else
|
else
|
||||||
ins->oprs[c - 0300].segment &= ~SEG_32BIT;
|
ins->oprs[c - 0300].segment &= ~SEG_32BIT;
|
||||||
a_used = TRUE;
|
a_used = TRUE;
|
||||||
}
|
} else if (c == 0310) {
|
||||||
if (c == 0310) {
|
|
||||||
if (asize != 16)
|
if (asize != 16)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
a_used = TRUE;
|
a_used = TRUE;
|
||||||
}
|
} else if (c == 0311) {
|
||||||
if (c == 0311) {
|
|
||||||
if (asize == 16)
|
if (asize == 16)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
a_used = TRUE;
|
a_used = TRUE;
|
||||||
}
|
} else if (c == 0312) {
|
||||||
if (c == 0312) {
|
|
||||||
if (asize != segsize)
|
if (asize != segsize)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
a_used = TRUE;
|
a_used = TRUE;
|
||||||
}
|
} else if (c == 0320) {
|
||||||
if (c == 0320) {
|
|
||||||
if (osize != 16)
|
if (osize != 16)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
o_used = TRUE;
|
o_used = TRUE;
|
||||||
}
|
} else if (c == 0321) {
|
||||||
if (c == 0321) {
|
if (osize != 32)
|
||||||
if (osize == 16)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
o_used = TRUE;
|
o_used = TRUE;
|
||||||
}
|
} else if (c == 0322) {
|
||||||
if (c == 0322) {
|
|
||||||
if (osize != (segsize == 16) ? 16 : 32)
|
if (osize != (segsize == 16) ? 16 : 32)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
o_used = TRUE;
|
o_used = TRUE;
|
||||||
}
|
} else if (c == 0323) {
|
||||||
if (c == 0323) {
|
|
||||||
rex |= REX_W; /* 64-bit only instruction */
|
rex |= REX_W; /* 64-bit only instruction */
|
||||||
osize = 64;
|
osize = 64;
|
||||||
}
|
} else if (c == 0324) {
|
||||||
if (c == 0324) {
|
if (!(rex & REX_P) || osize != 64)
|
||||||
if (!(rex & REX_P))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
} else if (c == 0330) {
|
||||||
if (c == 0330) {
|
|
||||||
int t = *r++, d = *data++;
|
int t = *r++, d = *data++;
|
||||||
if (d < t || d > t + 15)
|
if (d < t || d > t + 15)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
ins->condition = d - t;
|
ins->condition = d - t;
|
||||||
}
|
} else if (c == 0331) {
|
||||||
if (c == 0331) {
|
|
||||||
if (rep)
|
if (rep)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
} else if (c == 0332) {
|
||||||
if (c == 0332) {
|
|
||||||
if (drep == P_REP)
|
if (drep == P_REP)
|
||||||
drep = P_REPE;
|
drep = P_REPE;
|
||||||
}
|
} else if (c == 0333) {
|
||||||
if (c == 0333) {
|
|
||||||
if (rep != 0xF3)
|
if (rep != 0xF3)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
drep = 0;
|
drep = 0;
|
||||||
|
@ -708,7 +708,7 @@ MOV reg64,reg64 \321\1\x8B\110 X64
|
|||||||
MOV reg8,imm \10\xB0\21 8086,SM
|
MOV reg8,imm \10\xB0\21 8086,SM
|
||||||
MOV reg16,imm \320\10\xB8\31 8086,SM
|
MOV reg16,imm \320\10\xB8\31 8086,SM
|
||||||
MOV reg32,imm \321\10\xB8\41 386,SM
|
MOV reg32,imm \321\10\xB8\41 386,SM
|
||||||
MOV reg64,imm \321\10\xB8\55 X64,SM
|
MOV reg64,imm \324\10\xB8\55 X64,SM
|
||||||
MOV rm8,imm \300\1\xC6\200\21 8086,SM
|
MOV rm8,imm \300\1\xC6\200\21 8086,SM
|
||||||
MOV rm16,imm \320\300\1\xC7\200\31 8086,SM
|
MOV rm16,imm \320\300\1\xC7\200\31 8086,SM
|
||||||
MOV rm32,imm \321\300\1\xC7\200\41 386,SM
|
MOV rm32,imm \321\300\1\xC7\200\41 386,SM
|
||||||
|
Loading…
Reference in New Issue
Block a user