// 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 _CRT_SECURE_NO_WARNINGS
#define STRICT
#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"
////////////////////////////////////////////////////////////////////////////////
///////////////////////////// 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);
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
- 1
- 2
- 3
- 4
前往页