JMP instructions use the operand size prefix, not the address size

prefix, to determine the size of the jump target.
This commit is contained in:
H. Peter Anvin 2002-05-21 03:31:21 +00:00
parent 01377d8d7c
commit 17799b40c0
3 changed files with 30 additions and 11 deletions

12
CHANGES
View File

@ -1,3 +1,15 @@
0.98.33
-------
* New __NASM_PATCHLEVEL__ and __NASM_VERSION_ID__ standard macros to
round out the version-query macros. version.pl now understands
X.YYplWW or X.YY.ZZplWW as a version number, equivalent to
X.YY.ZZ.WW (or X.YY.0.WW, as appropriate).
* New keyword "strict" to disable the optimization of a specific
operand.
* Fix the handing of size overrides with JMP instructions
(instructions such as "jmp dword foo".)
0.98.32
-------

View File

@ -28,7 +28,7 @@
* \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
* \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
* \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
* assembly mode or the address-size override on the operand
* assembly mode or the operand-size override on the operand
* \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
* \1ab - a ModRM, calculated on EA in operand a, with the spare
* field the register value of operand b.
@ -601,8 +601,11 @@ static long calcsize (long segment, long offset, int bits,
case 060: case 061: case 062:
length += 2; break;
case 064: case 065: case 066:
length += ((ins->oprs[c-064].addr_size ?
ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
if ( ins->oprs[c-064].type & (BITS16|BITS32) )
length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
else
length += (bits == 16) ? 2 : 4;
break;
case 070: case 071: case 072:
length += 4; break;
case 0130: case 0131: case 0132:
@ -849,14 +852,15 @@ static void gencode (long segment, long offset, int bits,
break;
case 064: case 065: case 066:
size = ((ins->oprs[c-064].addr_size ?
ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
if ( ins->oprs[c-064].type & (BITS16|BITS32) )
size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
else
size = (bits == 16) ? 2 : 4;
if (ins->oprs[c-064].segment != segment) {
long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
data = ins->oprs[c-064].offset;
size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
out (offset, segment, &data, size+insn_end-offset,
out (offset, segment, &data, reltype+insn_end-offset,
ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
size = (bits == 16 ? 2 : 4);
} else {
data = ins->oprs[c-064].offset - insn_end;
out (offset, segment, &data,

View File

@ -360,15 +360,18 @@ static int matches (struct itemplate *t, unsigned char *data, int asize,
if (c >= 064 && c <= 066) {
ins->oprs[c-064].offset = *data++;
ins->oprs[c-064].offset |= (*data++ << 8);
if (asize == 32) {
if (osize == 32) {
ins->oprs[c-064].offset |= (((long) *data++) << 16);
ins->oprs[c-064].offset |= (((long) *data++) << 24);
ins->oprs[c-064].segment |= SEG_32BIT;
} else
ins->oprs[c-064].segment &= ~SEG_32BIT;
ins->oprs[c-064].segment |= SEG_RELATIVE;
if (segsize != asize)
ins->oprs[c-064].addr_size = asize;
if (segsize != osize) {
ins->oprs[c-064].type =
(ins->oprs[c-064].type & NON_SIZE)
| ((osize == 16) ? BITS16 : BITS32);
}
}
if (c >= 070 && c <= 072) {
ins->oprs[c-070].offset = *data++;