objemit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 807 行 · 第 1/2 页
C
807 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "disasm.h"
#include "wdismsg.h"
static char *RetFMacro[] = {
" MACRO POP_COUNT",
" LOCAL DUMMY",
" DUMMY PROC FAR",
" RET POP_COUNT",
" DUMMY ENDP",
" ENDM",
NULL
};
static char *DOSAlignTxt[] = {
"SEGMENT", /* used for COMDAT's */
"BYTE",
"WORD",
"PARA",
"PAGE",
"DWORD",
"PAGE4K",
};
static char *UnixAlignTxt[] = {
"section", /* used for COMDAT's */
"1",
"2",
"16",
"256",
"4",
"4096",
};
static char *MatchTxt[] = {
"NONE",
"ANY",
"SIZE",
"EXACT",
};
static char *AllocTxt[] = {
NULL,
"FAR CODE",
"FAR DATA",
"CODE32",
"DATA32",
};
/*
* Static function prototypes
*/
static void EmitSegAlign( void );
static void EmitSegCombine( void );
static void EmitOrg( uint_32 origin );
static void EmitRetFMacro( void );
void EmitModule()
/****************/
{
char *name;
import_sym *imp;
char sp_buf[ _MAX_PATH2 ];
char *root_name;
if( ( Options & FORM_ASSEMBLER ) == 0 ) {
EmitNL();
DoEmit( MSG_MODULE );
EmitLine( Mod->name );
if( Mod->main ) {
EmitLine( "MAIN MODULE " );
}
if( Mod->start != NULL ) {
DoEmit( MSG_START_ADDR );
name = GetFixName( Mod->start );
if( name == NULL ) {
name = NewName( Mod->start );
}
Emit( name );
EmitNL();
}
} else {
_splitpath2( Mod->name, sp_buf, NULL, NULL, &root_name, NULL );
if( DO_UNIX ) {
EmitBlanks( LABEL_LEN );
EmitSpaced( ".file", OPCODE_LEN );
Emit( "\"" );
Emit( root_name );
Emit( "\"" );
EmitNL();
} else {
if( RetFarUsed ) {
EmitRetFMacro();
}
if( Is32BitObj ) EmitLine( ".386p" );
EmitBlanks( LABEL_LEN );
EmitSpaced( "NAME", OPCODE_LEN );
EmitLine( root_name );
}
if( ( Options & FORM_DO_WTK ) && HaveWtk() ) {
Emit( "INCLUDE" );
EmitBlanks( LABEL_LEN - 7 );
EmitLine( "67MACROS.EQU" );
}
}
for( imp = Mod->imports; imp != NULL; imp = imp->next_imp ) {
switch( imp->class ) {
case TYPE_IMPORT:
if( !DO_UNIX
&& ( Options & FORM_ASSEMBLER )
&& imp->public
&& !imp->exported
&& strcmp( imp->name, WTLBASEStr ) != 0 ) {
EmitBlanks( LABEL_LEN );
EmitSpaced( "EXTRN", OPCODE_LEN );
EmitSym( imp->name, 0 );
Emit( ":BYTE" ); // so that output would assemble
EmitNL();
}
break;
case TYPE_COMDEF:
if( DO_UNIX ) {
if( imp->public ) {
EmitBlanks( LABEL_LEN );
EmitSpaced( ".globl", OPCODE_LEN );
EmitLine( imp->name );
}
EmitBlanks( LABEL_LEN );
EmitSpaced( ".lcomm", OPCODE_LEN );
EmitSym( imp->name, 0 );
Emit( ", " );
} else {
if( imp->public ) {
EmitBlanks( LABEL_LEN );
EmitSpaced( "COMM", OPCODE_LEN );
} else {
if( Options & FORM_ASSEMBLER ) {
DoEmitError( MSG_LCL_COMM_WONT_ASM );
}
EmitBlanks( LABEL_LEN );
EmitSpaced( "LCOMM", OPCODE_LEN );
}
if( imp->far_common ) {
Emit( "FAR " );
} else {
Emit( "NEAR " );
}
EmitSym( imp->name, 0 );
Emit( ":BYTE:" );
}
EmitHex( imp->u.size );
EmitNL();
break;
}
FreeSymTranslations();
}
}
void EmitEndMod()
/****************/
{
EmitSrc();
if( Options & FORM_ASSEMBLER ) {
if( !DO_UNIX ) {
EmitBlanks( LABEL_LEN );
EmitLine( "END" );
}
} else {
DumpSymList();
}
}
void EmitGroup( group *grp )
/***************************/
{
handle *entry;
segment *seg;
bool found;
if( grp->name != NULL ) {
entry = grp->list;
found = FALSE;
while( entry != NULL ) {
seg = (segment *)entry->data;
if( !found ) {
found = TRUE;
if( Options & FORM_ASSEMBLER ) {
EmitSpaced( grp->name, LABEL_LEN );
EmitSpaced( "GROUP", OPCODE_LEN );
} else {
DoEmit( MSG_GROUP );
Emit( "'" );
Emit( grp->name );
Emit( "' " );
}
} else {
Emit( "," );
}
Emit( seg->name );
entry = entry->next_hndl;
}
if( found ) EmitNL();
}
}
void EmitSegment()
/*****************/
{
export_sym *exp;
char numbuff[ 16 ];
group *grp;
if( Segment->name != NULL ) {
if( Options & FORM_ASSEMBLER ) {
if( DO_UNIX ) {
if( !Segment->data_seg ) {
EmitLine( ".text" );
} else if( stricmp( Segment->name, "_BSS" ) == 0 ) {
EmitLine( ".bss" );
} else {
EmitLine( ".data" );
}
if( Segment->class == TYPE_SEGMENT ) {
EmitBlanks( LABEL_LEN );
Emit( ".align " );
EmitLine( UnixAlignTxt[ _SegAlign( Segment ) ] );
} else {
//NYI: don't know what to do with comdat's
EmitNL();
}
} else {
if( Segment->class == TYPE_COMDAT ) {
if( Options & FORM_ASSEMBLER ) {
DoEmitError( MSG_COMDAT_WONT_ASM );
}
EmitSym( Segment->name, LABEL_LEN );
EmitSpaced( "COMDAT", OPCODE_LEN );
} else {
EmitSpaced( Segment->name, LABEL_LEN );
EmitSpaced( "SEGMENT", OPCODE_LEN );
}
EmitSegAlign();
EmitSegCombine();
EmitSegUse();
EmitSegAccess();
if( Segment->class == TYPE_SEGMENT ) {
Emit( "'" );
Emit( Segment->u.seg.class_name );
Emit( "'" );
}
EmitNL();
if( !Segment->data_seg ) {
EmitBlanks( LABEL_LEN );
Emit( "ASSUME CS:" );
grp = Segment->grouped;
if( grp != NULL ) {
Emit( grp->name );
} else {
EmitSegName( Segment, 0 );
}
EmitLine( ",DS:DGROUP,SS:DGROUP" );
}
}
exp = Segment->exports;
while( exp != NULL ) {
if( exp->public ) {
EmitBlanks( LABEL_LEN );
if( DO_UNIX ) {
EmitSpaced( ".globl", OPCODE_LEN );
} else {
EmitSpaced( "PUBLIC", OPCODE_LEN );
}
EmitSym( exp->name, 0 );
EmitNL();
}
exp = exp->next_exp;
}
} else {
EmitNL();
if( Segment->class == TYPE_COMDAT ) {
DoEmit( MSG_COMDAT );
} else {
DoEmit( MSG_SEGMENT );
}
EmitSegName( Segment, 0 );
Emit( " " );
EmitSegAlign();
EmitSegUse();
EmitSegAccess();
if( _Size64K( Segment ) ) {
strcpy( numbuff, "10000" );
} else {
EmitAddr( Segment->size, WORD_SIZE, numbuff );
}
SubStrEmit( MSG_BYTES, numbuff, 's' );
if( Segment->offset != BAD_OFFSET ) {
DoEmit( MSG_LOCATION );
EmitAddr( Segment->address, WORD_SIZE, NULL );
IToHS( numbuff, Segment->offset, 1 );
numbuff[1] = NULLCHAR;
Emit( numbuff );
}
EmitNL();
}
}
}
static void EmitSegAlign( void )
/********************************/
{
unsigned align;
align = (Segment->class == TYPE_COMDAT)
? _ComdatAlign( Segment ) : _SegAlign( Segment );
Emit( DOSAlignTxt[ align ] );
Emit( " " );
}
static void EmitSegUse( void )
/******************************/
{
if( Segment->class == TYPE_COMDAT ) {
Emit( MatchTxt[ _ComdatMatch( Segment ) ] );
Emit( " " );
if( Segment->u.com.grp != NULL ) {
Emit( "'" );
Emit( Segment->u.com.grp->name );
if( Segment->u.com.seg != NULL ) {
Emit( ":" );
Emit( Segment->u.com.seg->name );
}
Emit( "'" );
} else if( Segment->u.com.seg != NULL ) {
Emit( "'" );
Emit( Segment->u.com.seg->name );
Emit( "'" );
} else {
Emit( AllocTxt[ _ComdatAlloc( Segment ) ] );
}
} else if( Segment->use_32 ) {
Emit( "USE32" );
} else if( Is32BitObj ) {
Emit( "USE16" );
}
Emit( " " );
}
static void EmitSegAccess( void )
/*******************************/
{
if( IsPharLap && Segment->access_valid ) {
switch( Segment->access_attr ) {
case EASY_READ_ONLY: Emit( "RO " ); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?