📄 operands.c
字号:
/*
Copyright 2001-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
**********************************************************************
OPERANDS.C defines various callback functions that parse machine
code byte streams and turn them into the operands of an assembly
language instruction. The opcode table in OPCODES.C indexes each
opcode against various bit patterns, then determines what parsing
should be used to determine the operands. Eventually one of these
routines is called to do the actual parsing.
**********************************************************************
*/
#include "opcodes.h"
#include "operands.h"
#include <string.h>
#include <stdio.h>
#define SZ_QWORD 2
#define SZ_TBYTE 4
long code_address;
static BOOL strict;
static uint segs, total_prefixes;
static char mnemonic[10];
static OPERAND extraoperand, source, dest;
static char *based[8] =
{
"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
};
static char *st[8] =
{
"dword", "dword", "qword", "word", "tbyte"
};
static void SetSeg(OPERAND *record, uint seg)
{
strict = FALSE;
record->code = OM_SEGMENT;
record->reg = seg;
}
//-------------------------------------------------------------------------
static void SetReg(OPERAND *record, uint reg)
{
strict = FALSE;
record->code = OM_REG;
record->reg = reg;
}
//-------------------------------------------------------------------------
uint ReadRM(BYTE *stream, OPERAND *record)
{
int mod, ofs = 2;
/* Init the register or base index */
record->reg = RM(stream);
/* if MOD = 3 it's a register, we get out */
if ((mod = MOD(stream)) == MOD_REG)
{
record->code = OM_REG;
strict = FALSE;
return (0);
}
if (record->flags &OMF_ADR32)
/* If is scaled op */
if (record->reg == RM_32_SCALED)
{
/* bump the index ptr and get the SIB ops */
ofs++;
record->reg = RM(stream + 1);
record->scalereg = REG(stream + 1);
record->scale = MOD(stream + 1);
/* Can only scale if scale reg not SP */
if (!(record->scalereg == RM_32_STACKINDEX))
record->flags |= OMF_SCALED;
/* now see if it is absolute scaled */
if ((record->reg == RM_32_ABSOLUTE) && (mod == MOD_NOOFS))
{
record->code = OM_ABSOLUTE;
record->address = LONG(stream + 3);
return (5);
}
}
else
{
if ((mod == MOD_NOOFS) && (record->reg == RM_32_ABSOLUTE))
{
record->code = OM_ABSOLUTE;
record->address = LONG(stream + 2);
return (4);
}
}
else
if ((mod == MOD_NOOFS) && (record->reg == RM_16_ABSOLUTE))
{
record->code = OM_ABSOLUTE;
record->address = UINT(stream + 2);
return (2);
}
/* If we get this far we are based and possibly scaled */
record->code = OM_BASED;
if (mod == MOD_ADDR)
{
record->flags |= OMF_WORD_OFFSET;
if (record->flags &OMF_ADR32)
{
record->address = LONG(stream + ofs);
ofs += 4;
}
else
{
record->address = UINT(stream + ofs);
ofs += 2;
}
}
else
if (mod == MOD_SIGNED)
{
record->flags |= OMF_SIGNED_OFFSET;
record->address = SIGNEDOFS(stream + ofs);
ofs++;
}
return (ofs - 2);
}
//-------------------------------------------------------------------------
uint RegRM(BYTE *stream, OPERAND *reg, OPERAND *rm)
{
SetReg(reg, REG(stream));
return (ReadRM(stream, rm));
}
//-------------------------------------------------------------------------
uint Immediate(BYTE *stream, OPERAND *imm)
{
int ofs = 0;
imm->code = OM_IMMEDIATE;
if (imm->flags &OMF_BYTE)
imm->address = *(stream + (ofs++));
else
if (imm->flags &OMF_OP32)
{
imm->address = LONG(stream + ofs);
ofs += 4;
}
else
{
imm->address = UINT(stream + ofs);
ofs += 2;
}
return (ofs);
}
//-------------------------------------------------------------------------
static void MnemonicChar(char theChar)
{
int pos = strlen(mnemonic);
mnemonic[pos + 1] = '\0';
mnemonic[pos] = theChar;
}
/* op 1- word reg from bits 0 - 2 of opcode */
static uint OP1(BYTE *stream, OPERAND *dest)
{
dest->flags &= ~OMF_BYTE;
SetReg(dest, B02(*stream));
return (0);
}
/* OP1 acc, reg bits 0-2 of opcode */
static uint OP2(BYTE *stream, OPERAND *dest, OPERAND *source)
{
source->flags = dest->flags = 0;
SetReg(dest, REG_eAX);
SetReg(source, B02(*stream));
return (0);
}
/* op3 - seg from b3-5 of opcode */
static uint OP3(BYTE *stream, OPERAND *dest)
{
SetSeg(dest, B35(*stream));
return (0);
}
/* op4 - REGRM with b1 of opcode set reg is dest else source */
static uint OP4(BYTE *stream, OPERAND *dest, OPERAND *source)
{
if (B1(*stream))
return (RegRM(stream, dest, source));
/* Reg is dest */
return (RegRM(stream, source, dest)); /* Reg is source */
}
/* op5 - use RM only */
static uint OP5(BYTE *stream, OPERAND *dest)
{
return (ReadRM(stream, dest));
}
/* op6 READRM for shift */
static uint OP6(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs = ReadRM(stream, dest);
source->code = OM_SHIFT;
if (B4(*stream))
if (B1(*stream))
source->flags |= OMF_CL;
else
source->address = 1;
else
source->address = *(stream + 2+(ofs++));
return (ofs);
}
/* op 7 regrm with reg dest */
static uint OP7(BYTE *stream, OPERAND *dest, OPERAND *source)
{
return (RegRM(stream, dest, source));
}
/* OP8 - word regrm with reg dest */
static uint OP8(BYTE *stream, OPERAND *dest, OPERAND *source)
{
dest->flags &= ~OMF_BYTE;
source->flags &= ~OMF_BYTE;
return (RegRM(stream, dest, source));
}
/* op 9 - interrupts */
static uint OP9(BYTE *stream, OPERAND *dest)
{
strict = FALSE;
dest->code = OM_INT;
if (B0(*stream))
{
dest->address = *(stream + 1);
return (0);
}
dest->address = 3;
return (0);
}
/* op 10, short relative branch */
static uint OP10(BYTE *stream, OPERAND *dest)
{
strict = FALSE;
dest->code = OM_SHORTBRANCH;
dest->address = code_address + SIGNEDOFS(stream + 1) + 2+total_prefixes;
if (!(dest->flags &OMF_OP32))
dest->address = dest->address &0xffff;
return (0);
}
/* op 11 RM, immediate */
static uint OP11(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs = ReadRM(stream, dest);
ofs += Immediate(stream + ofs + 2, source);
return (ofs);
}
/* op 12 - acc, immediate */
static uint OP12(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs;
SetReg(dest, REG_eAX);
ofs = Immediate(stream + 1, source);
return (ofs);
}
/* op 13 absolute, acc*/
static uint OP13(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs = 0;
dest->code = OM_ABSOLUTE;
if (dest->flags &OMF_ADR32)
{
dest->address = LONG(stream + 1);
ofs += 2;
}
else
dest->address = UINT(stream + 1);
SetReg(source, REG_eAX);
return (ofs);
}
/* op 14 - RM, immediate, b01 of opcode != 1 for byte */
static uint OP14(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs = ReadRM(stream, dest);
if (B01(*stream) == 0)
{
source->flags |= OMF_BYTE;
dest->flags |= OMF_BYTE;
}
else
{
if (B01(*stream) == 1)
source->flags &= ~OMF_BYTE;
else
source->flags |= OMF_BYTE;
dest->flags &= ~OMF_BYTE;
}
ofs += Immediate(stream + 2+ofs, source);
if (((*stream &3) == 3) && (source->flags &OMF_BYTE))
{
source->flags |= OMF_SIGNED;
source->address = (long)((char)source->address);
}
return (ofs);
}
/* op 15 - acc, immediate, B3 of opcode clear for byte */
static uint OP15(BYTE *stream, OPERAND *dest, OPERAND *source)
{
SetReg(dest, B02(*stream)); /* Not using OPSIZ */
if (B3(*stream))
{
source->flags &= ~OMF_BYTE;
dest->flags &= ~OMF_BYTE;
}
else
{
source->flags |= OMF_BYTE;
dest->flags |= OMF_BYTE;
}
return (Immediate(stream + 1, source));
}
/* op 16 - seg,readrm, if B1 of opcode seg is dest else source */
static uint OP16(BYTE *stream, OPERAND *dest, OPERAND *source)
{
int ofs;
if (B1(*stream))
{
SetSeg(dest, REG(stream));
source->flags &= ~OMF_BYTE;
ofs = ReadRM(stream, source);
}
else
{
dest->flags &= ~OMF_BYTE;
ofs = ReadRM(stream, dest);
SetSeg(source, REG(stream));
}
return (ofs);
}
/* op 17, far return */
static uint OP17(BYTE *stream, OPERAND *dest)
{
strict = FALSE;
dest->code = OM_RETURN;
dest->flags &= ~(OMF_ADR32 | OMF_OP32 | OMF_BYTE);
dest->address = UINT(stream + 1);
return (0);
}
/* op 18, far branch/call */
static uint OP18(BYTE *stream, OPERAND *dest)
{
int ofs = 0;
strict = FALSE;
dest->code = OM_FARBRANCH;
dest->flags &= ~OMF_BYTE;
if (dest->flags &OMF_OP32)
{
dest->address = LONG(stream + 1);
ofs += 2;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -