obj2asm.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 575 行 · 第 1/2 页
C
575 行
/****************************************************************************
*
* 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 <string.h>
#include <stdlib.h>
#include "disasm.h"
#include "wdismsg.h"
#ifdef __PCODE__
extern int SwitchCount;
#endif
/*
* Static function prototypes
*/
static void DecodeData( void );
static void DecodeCode( void );
static uint_32 GetNextFix( void );
static uint_32 GetNextLabel( void );
static scan_table *InScanTable( void );
void Obj2Asm( segment *seg )
/***************************/
{
if( !seg->dumped ) {
Segment = seg;
if( seg->last_export == NULL ) seg->last_export = seg->exports;
if( seg->last_fix == NULL ) seg->last_fix = seg->fixes;
EmitSegment();
InitSegAccess();
InitAsm();
if( !EndOfSegment() ) {
if( Segment->data_seg ) {
DecodeData();
} else {
DecodeCode();
}
}
if( EndOfSegment() ) {
ForceLabels();
FiniAsm();
Segment->dumped = TRUE;
}
EmitEndSeg();
}
}
void FlipToSeg( segment *seg )
/****************************/
{
unsigned old_err;
unsigned old_datalen;
segment *old_seg;
old_seg = Segment;
old_err = ErrCount;
old_datalen = DataLen;
Obj2Asm( seg );
Segment = old_seg;
ErrCount = old_err;
DataLen = old_datalen;
}
static void ForceLabels()
/***********************/
{
char rc_buff[MAX_RESOURCE_SIZE];
uint_32 size;
export_sym *exp;
export_sym *curr;
if( (Options & FORM_ASSEMBLER) && (Pass == 2) ) {
curr = Segment->exports;
if( DO_UNIX ) {
if( curr != NULL && curr->address != 0 ) {
EmitSpaced( ".zero", LABEL_LEN+OPCODE_LEN );
EmitHex( curr->address );
EmitNL();
}
}
while( curr != NULL ) { /* emit labels in BSS seg or inside instr's */
if( !curr->dumped ) {
if( !Segment->data_seg ) {
MsgGet( MSG_ORG_MAY_NOT_ASSEM, rc_buff );
MsgSubStr( rc_buff, curr->name, 's' );
/* The following simulates a call to Error( RecNumber, FALSE ) */
PutText( MSG_ASTERISK_1 );
PutText( MSG_WARNING );
PutString( rc_buff );
PutText( MSG_ASTERISK_2 );
FPutEnd( stdout );
}
if( DO_UNIX ) {
exp = curr;
for( ;; ) {
exp = exp->next_exp;
if( exp == NULL ) {
size = Segment->size - curr->address;
break;
}
if( !exp->dumped ) {
size = exp->address - curr->address;
break;
}
}
EmitLabel( curr->name, size );
} else {
EmitLabel( curr->name, curr->address );
}
}
curr = curr->next_exp;
}
}
}
static char *MagicFixNames[] = {
"FIWRQQ",
"FIDRQQ",
"FIERQQ",
"FISRQQ",
"FJSRQQ",
"FICRQQ",
"FJCRQQ",
"FIARQQ",
"FJARQQ",
NULL
};
static int Is87Fix( fixup *fix )
/********************************/
{
char *fix_name;
char **table;
if( _Class( fix->target ) != TYPE_IMPORT ) return( FALSE );
fix_name = _Name( fix->target );
for( table = MagicFixNames; *table != NULL; ++table ) {
if( strcmp( fix_name, *table ) == 0 ) return( TRUE );
}
return( FALSE );
}
static void SwallowFix( fixup * fix )
/***********************************/
{
switch( _Class( fix ) ) {
case CL_LONG_POINTER: /* BASE + 32-bit offset */
GetDataWord();
/* no break! */
case CL_LONG:
case CL_POINTER:
GetDataWord();
break;
}
GetDataWord();
}
static uint_32 SizeDataInCode( uint_32 size )
/*******************************************/
{
uint curr_size; /* no need for uint_32 since max 4 */
export_sym *label;
/* never print more than 4 or 8 bytes at a time */
if( Options & FORM_ASSEMBLER ) {
if( size > 8 ) {
size = 8;
}
} else {
if( size > 4 ) {
size = 4;
}
}
/* only print bytes up to the next label */
label = Segment->last_export;
for( ;; ) {
if( label == NULL ) break;
if( label->address != InsAddr ) break;
/* not interested in possible label(s) at beginning of data */
label = label->next_exp;
}
if( label != NULL && label->address - InsAddr < size ) {
size = label->address - InsAddr;
}
/* At this point size > 0. Otherwise we are in big trouble */
/* only print bytes up to the next fixup */
curr_size = 0;
for(;;) {
GetDataByte();
++curr_size;
if( curr_size == size ) break;
if( FindFixup( InsAddr+curr_size, Segment ) ) break;
}
return( curr_size );
}
static void DecodeCode()
/************************/
{
fixup *fix;
char is_data;
char in_pcode;
scan_table *table;
instruction curr_ins; /* not used */
in_pcode = 0;
for(;;) {
EmitSrc();
if( EndOfSegment() ) break;
InsAddr = GetOffset();
DataBytes = 0;
is_data = FALSE;
fix = FindFixup( InsAddr, Segment );
if( fix != NULL && Is87Fix( fix ) ) {
fix = NULL;
}
if( fix != NULL ) {
SwallowFix( fix );
FindLabel( BAD_OFFSET, fix->imp_address, fix->target );
} else {
table = InScanTable();
if( table != NULL ) {
#ifdef __PCODE__
if( in_pcode != 1 ) {
if( SwitchCount == 0 && PeekDataByte() == 0x9A ) {
fix = FindFixup( InsAddr+1, Segment );
if( fix != NULL ) {
if( !(Options & FORM_ASSEMBLER) ) in_pcode = 1;
goto do_code;
}
}
}
if( in_pcode >= 2 ) {
DoPcode();
in_pcode = 3;
} else {
if( in_pcode == 1 ) {
if( GetDataByte() == 0xFF ) {
GetDataByte();
GetDataByte();
}
in_pcode = 2;
} else {
SizeDataInCode( table->ends - InsAddr );
}
}
#else
SizeDataInCode( table->ends - InsAddr );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?