📄 assembl.cpp
字号:
// Free Disassembler and Assembler -- Assembler
//
// Copyright (C) 2001 Oleh Yuschuk
//
// 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
// 16.01.2002 - corrected error in processing of immediate constants.
#define STRICT
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//#include <dir.h>
#include <math.h>
#include <float.h>
#pragma hdrstop
#include "disasm.h"
#pragma warning(disable:4996)//关闭旧函数声明警告
////////////////////////////////////////////////////////////////////////////////
///////////////////////////// ASSEMBLER FUNCTIONS //////////////////////////////
// Scanner modes.
#define SA_NAME 0x0001 // Don't try to decode labels
#define SA_IMPORT 0x0002 // Allow import pseudolabel
// Types of input tokens reported by scanner.
#define SCAN_EOL 0 // End of line
#define SCAN_REG8 1 // 8-bit register
#define SCAN_REG16 2 // 16-bit register
#define SCAN_REG32 3 // 32-bit register
#define SCAN_SEG 4 // Segment register
#define SCAN_FPU 5 // FPU register
#define SCAN_MMX 6 // MMX register
#define SCAN_CR 7 // Control register
#define SCAN_DR 8 // Debug register
#define SCAN_OPSIZE 9 // Operand size modifier
#define SCAN_JMPSIZE 10 // Jump size modifier
#define SCAN_LOCAL 11 // Address on stack in form LOCAL.decimal
#define SCAN_ARG 12 // Address on stack in form ARG.decimal
#define SCAN_PTR 20 // PTR in MASM addressing statements
#define SCAN_REP 21 // REP prefix
#define SCAN_REPE 22 // REPE prefix
#define SCAN_REPNE 23 // REPNE prefix
#define SCAN_LOCK 24 // LOCK prefix
#define SCAN_NAME 25 // Command or label
#define SCAN_ICONST 26 // Hexadecimal constant
#define SCAN_DCONST 27 // Decimal constant
#define SCAN_OFS 28 // Undefined constant
#define SCAN_FCONST 29 // Floating-point constant
#define SCAN_EIP 30 // Register EIP
#define SCAN_SIGNED 31 // Keyword "SIGNED" (in expressions)
#define SCAN_UNSIGNED 32 // Keyword "UNSIGNED" (in expressions)
#define SCAN_CHAR 33 // Keyword "CHAR" (in expressions)
#define SCAN_FLOAT 34 // Keyword "FLOAT" (in expressions)
#define SCAN_DOUBLE 35 // Keyword "DOUBLE" (in expressions)
#define SCAN_FLOAT10 36 // Keyword "FLOAT10" (in expressions)
#define SCAN_STRING 37 // Keyword "STRING" (in expressions)
#define SCAN_UNICODE 38 // Keyword "UNICODE" (in expressions)
#define SCAN_MSG 39 // Pseudovariable MSG (in expressions)
#define SCAN_SYMB 64 // Any other character
#define SCAN_IMPORT 65 // Import pseudolabel
#define SCAN_ERR 255 // Definitely bad item
// Definition used by Assembler to report command matching errors.
#define MA_JMP 0x0001 // Invalid jump size modifier
#define MA_NOP 0x0002 // Wrong number of operands
#define MA_TYP 0x0004 // Bad operand type
#define MA_NOS 0x0008 // Explicit operand size expected
#define MA_SIZ 0x0010 // Bad operand size
#define MA_DIF 0x0020 // Different operand sizes
#define MA_SEG 0x0040 // Invalid segment register
#define MA_RNG 0x0080 // Constant out of expected range
typedef struct t_asmoperand
{
int type; // Operand type, see beginning of file
int size; // Operand size or 0 if yet unknown
int index; // Index or other register
int scale; // Scale
int base; // Base register if present
long offset; // Immediate value or offset
int anyoffset; // Offset is present but undefined
int segment; // Segment in address if present
int jmpmode; // Specified jump size
} t_asmoperand;
static char *asmcmd; // Pointer to 0-terminated source line
static int scan; // Type of last scanned element
static int prio; // Priority of operation (0: highest)
static char sdata[TEXTLEN]; // Last scanned name (depends on type)
static long idata; // Last scanned value
static long double fdata; // Floating-point number
static char *asmerror; // Explanation of last error, or NULL
// Simple and slightly recursive scanner shared by Assemble(). The scanner is
// straightforward and ineffective, but high speed is not a must here. As
// input, it uses global pointer to source line asmcmd. On exit, it fills in
// global variables scan, prio, sdata, idata and/or fdata. If some error is
// detected, asmerror points to error message, otherwise asmerror remains
// unchanged.
static void Scanasm(int mode)
{
int i,j,base,maxdigit;
long decimal,hex;
long double floating,divisor;
char s[TEXTLEN],*pcmd;
sdata[0]='\0';
idata=0;
if (asmcmd==NULL)
{
asmerror="NULL input line";
scan=SCAN_ERR;
return;
};
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++; // Skip leading spaces
if (*asmcmd=='\0' || *asmcmd==';')
{
scan=SCAN_EOL;
return;
}; // Empty line
if (isalpha(*asmcmd) || *asmcmd=='_' || *asmcmd=='@')
{
sdata[0]=*asmcmd++; i=1; // Some keyword or identifier
while ((isalnum(*asmcmd) || *asmcmd=='_' || *asmcmd=='@') && i<sizeof(sdata))
sdata[i++]=*asmcmd++;
if (i>=sizeof(sdata))
{
asmerror="Too long identifier";
scan=SCAN_ERR;
return;
};
sdata[i]='\0';
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++; // Skip trailing spaces
strcpy(s,sdata); _strupr_s(s);
for (j=0; j<=8; j++)
{ // j==8 means "any register"
if (strcmp(s,regname[0][j])!=0)
continue;
idata=j;
scan=SCAN_REG8; // 8-bit register
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,regname[1][j])!=0)
continue;
idata=j;
scan=SCAN_REG16; // 16-bit register
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,regname[2][j])!=0)
continue;
idata=j;
scan=SCAN_REG32; // 32-bit register
return;
};
for (j=0; j<6; j++)
{
if (strcmp(s,segname[j])!=0)
continue;
idata=j;
scan=SCAN_SEG; // Segment register
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++; // Skip trailing spaces
return;
};
if (strcmp(s,"ST")==0)
{
pcmd=asmcmd;
Scanasm(SA_NAME); // FPU register
if (scan!=SCAN_SYMB || idata!='(')
{
asmcmd=pcmd; // Undo last scan
idata=0; scan=SCAN_FPU;
return;
};
Scanasm(SA_NAME);
j=idata;
if ((scan!=SCAN_ICONST && scan!=SCAN_DCONST) || idata<0 || idata>7)
{
asmerror="FPU registers have indexes 0 to 7";
scan=SCAN_ERR;
return;
};
Scanasm(SA_NAME);
if (scan!=SCAN_SYMB || idata!=')')
{
asmerror="Closing parenthesis expected";
scan=SCAN_ERR;
return;
};
idata=j; scan=SCAN_FPU;
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,fpuname[j])!=0)
continue;
idata=j;
scan=SCAN_FPU; // FPU register (alternative coding)
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,mmxname[j])!=0)
continue;
idata=j; scan=SCAN_MMX; // MMX register
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,crname[j])!=0)
continue;
idata=j;
scan=SCAN_CR; // Control register
return;
};
for (j=0; j<=8; j++)
{
if (strcmp(s,drname[j])!=0)
continue;
idata=j;
scan=SCAN_DR; // Debug register
return;
};
for (j=0; j<sizeof(sizename)/sizeof(sizename[0]); j++)
{
if (strcmp(s,sizename[j])!=0)
continue;
pcmd=asmcmd; Scanasm(SA_NAME);
if (scan!=SCAN_PTR) // Fetch non-functional "PTR"
asmcmd=pcmd;
idata=j;
scan=SCAN_OPSIZE; // Operand (data) size in bytes
return;
};
if (strcmp(s,"EIP")==0)
{ // Register EIP
scan=SCAN_EIP;
idata=0;
return;
};
if (strcmp(s,"SHORT")==0)
{ // Relative jump has 1-byte offset
scan=SCAN_JMPSIZE; idata=1;
return;
};
if (strcmp(s,"LONG")==0)
{ // Relative jump has 4-byte offset
scan=SCAN_JMPSIZE; idata=2;
return;
};
if (strcmp(s,"NEAR")==0)
{ // Jump within same code segment
scan=SCAN_JMPSIZE; idata=4;
return;
};
if (strcmp(s,"FAR")==0)
{ // Jump to different code segment
scan=SCAN_JMPSIZE; idata=8;
return;
};
if (strcmp(s,"LOCAL")==0 && *asmcmd=='.') {
asmcmd++;
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++; // Skip trailing spaces
if (!isdigit(*asmcmd))
{
asmerror="Integer number expected";
scan=SCAN_ERR;
return;
};
while (isdigit(*asmcmd)) // LOCAL index is decimal number!
idata=idata*10+(*asmcmd++)-'0';
scan=SCAN_LOCAL;
return;
};
if (strcmp(s,"ARG")==0 && *asmcmd=='.')
{
asmcmd++;
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++; // Skip trailing spaces
if (!isdigit(*asmcmd))
{
asmerror="Integer number expected";
scan=SCAN_ERR; return;
};
while (isdigit(*asmcmd)) // ARG index is decimal number!
idata=idata*10+(*asmcmd++)-'0';
scan=SCAN_ARG;
return;
};
if (strcmp(s,"REP")==0)
{
scan=SCAN_REP;
return;
}; // REP prefix
if (strcmp(s,"REPE")==0 || strcmp(s,"REPZ")==0)
{
scan=SCAN_REPE;
return;
}; // REPE prefix
if (strcmp(s,"REPNE")==0 || strcmp(s,"REPNZ")==0)
{
scan=SCAN_REPNE;
return;
}; // REPNE prefix
if (strcmp(s,"LOCK")==0)
{
scan=SCAN_LOCK;
return;
}; // LOCK prefix
if (strcmp(s,"PTR")==0)
{
scan=SCAN_PTR;
return;
}; // PTR in MASM addressing statements
if (strcmp(s,"CONST")==0 || strcmp(s,"OFFSET")==0)
{
scan=SCAN_OFS;
return;
}; // Present but undefined offset/constant
if (strcmp(s,"SIGNED")==0)
{
scan=SCAN_SIGNED;
return;
}; // Keyword "SIGNED" (in expressions)
if (strcmp(s,"UNSIGNED")==0)
{
scan=SCAN_UNSIGNED;
return;
}; // Keyword "UNSIGNED" (in expressions)
if (strcmp(s,"CHAR")==0)
{
scan=SCAN_CHAR; return;
}; // Keyword "CHAR" (in expressions)
if (strcmp(s,"FLOAT")==0)
{
scan=SCAN_FLOAT;
return;
}; // Keyword "FLOAT" (in expressions)
if (strcmp(s,"DOUBLE")==0)
{
scan=SCAN_DOUBLE;
return;
}; // Keyword "DOUBLE" (in expressions)
if (strcmp(s,"FLOAT10")==0)
{
scan=SCAN_FLOAT10;
return;
}; // Keyword "FLOAT10" (in expressions)
if (strcmp(s,"STRING")==0)
{
scan=SCAN_STRING;
return;
}; // Keyword "STRING" (in expressions)
if (strcmp(s,"UNICODE")==0)
{
scan=SCAN_UNICODE;
return;
}; // Keyword "UNICODE" (in expressions)
if (strcmp(s,"MSG")==0)
{
scan=SCAN_MSG;
return;
}; // Pseudovariable MSG (in expressions)
if (mode & SA_NAME)
{
idata=i;
scan=SCAN_NAME; // Don't try to decode symbolic label
return;
}
asmerror="Unknown identifier";
scan=SCAN_ERR;
return;
}
else if (isdigit(*asmcmd))
{ // Constant
base=0; maxdigit=0; decimal=hex=0L; floating=0.0;
if (asmcmd[0]=='0' && toupper(asmcmd[1])=='X')
{
base=16; asmcmd+=2;
}; // Force hexadecimal number
while (1)
{
if (isdigit(*asmcmd))
{
decimal=decimal*10+(*asmcmd)-'0';
floating=floating*10.0+(*asmcmd)-'0';
hex=hex*16+(*asmcmd)-'0';
if (maxdigit==0)
maxdigit=9;
asmcmd++;
}
else if (isxdigit(*asmcmd))
{
hex=hex*16+toupper(*asmcmd++)-'A'+10;
maxdigit=15;
}
else
break;
};
if (maxdigit==0)
{
asmerror="Hexadecimal digits after 0x... expected";
scan=SCAN_ERR;
return;
};
if (toupper(*asmcmd)=='H')
{ // Force hexadecimal number
if (base==16)
{
asmerror="Please don't mix 0xXXXX and XXXXh forms";
scan=SCAN_ERR;
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -