📄 outieee.c
字号:
}
i++;
pub = pub->next;
}
/*
* Write the externals
*/
ext = exthead;
i = 1;
while (ext) {
char buf[256];
ieee_unqualified_name(buf, ext->name);
ieee_putascii("NX%X,%02X%s.\r\n", i++, strlen(buf), buf);
ext = ext->next;
}
ieee_putcs(FALSE);
/*
* IEEE doesn't have a standard pass break record
* so use the ladsoft variant
*/
ieee_putascii("CO100,06ENDSYM.\r\n");
/*
* now put types
*/
i = ARRAY_BOT;
for (arr = arrhead; arr && debuginfo; arr = arr->next) {
ieee_putascii("TY%X,20,%X,%lX.\r\n", i++, arr->basetype,
arr->size);
}
/*
* now put locals
*/
i = 1;
for (seg = seghead; seg && debuginfo; seg = seg->next) {
for (loc = seg->lochead; loc; loc = loc->next) {
char buf[256];
ieee_unqualified_name(buf, loc->name);
ieee_putascii("NN%X,%02X%s.\r\n", i, strlen(buf), buf);
if (loc->segment == -1)
ieee_putascii("ASN%X,R%X,%lX,+.\r\n", i, loc->index,
loc->offset);
else
ieee_putascii("ASN%X,%lX,%lX,+.\r\n", i, loc->segment * 16,
loc->offset);
if (debuginfo) {
if (loc->type >= 0x100)
ieee_putascii("ATN%X,T%X.\r\n", i, loc->type - 0x100);
else
ieee_putascii("ATN%X,%X.\r\n", i, loc->type);
}
i++;
}
}
/*
* put out section data;
*/
seg = seghead;
if (!debuginfo && !strcmp(seg->name, "??LINE"))
seg = seg->next;
while (seg) {
if (seg->currentpos) {
long size, org = 0;
data = seg->data;
ieee_putascii("SB%X.\r\n", seg->ieee_index);
fix = seg->fptr;
while (fix) {
size = HUNKSIZE - (org % HUNKSIZE);
size =
size + org >
seg->currentpos ? seg->currentpos - org : size;
size = fix->offset - org > size ? size : fix->offset - org;
org = ieee_putld(org, org + size, data->data);
if (org % HUNKSIZE == 0)
data = data->next;
if (org == fix->offset) {
org += ieee_putlr(fix);
fix = fix->next;
}
}
while (org < seg->currentpos && data) {
size =
seg->currentpos - org >
HUNKSIZE ? HUNKSIZE : seg->currentpos - org;
org = ieee_putld(org, org + size, data->data);
data = data->next;
}
ieee_putcs(FALSE);
}
seg = seg->next;
}
/*
* module end record
*/
ieee_putascii("ME.\r\n");
}
static void ieee_write_byte(struct ieeeSection *seg, int data)
{
int temp;
if (!(temp = seg->currentpos++ % HUNKSIZE))
ieee_data_new(seg);
seg->datacurr->data[temp] = data;
}
static void ieee_write_word(struct ieeeSection *seg, int data)
{
ieee_write_byte(seg, data & 0xFF);
ieee_write_byte(seg, (data >> 8) & 0xFF);
}
static void ieee_write_dword(struct ieeeSection *seg, long data)
{
ieee_write_byte(seg, data & 0xFF);
ieee_write_byte(seg, (data >> 8) & 0xFF);
ieee_write_byte(seg, (data >> 16) & 0xFF);
ieee_write_byte(seg, (data >> 24) & 0xFF);
}
static void ieee_putascii(char *format, ...)
{
char buffer[256];
int i, l;
va_list ap;
va_start(ap, format);
vsprintf(buffer, format, ap);
l = strlen(buffer);
for (i = 0; i < l; i++)
if ((buffer[i] & 0xff) > 31)
checksum += buffer[i];
va_end(ap);
fprintf(ofp, buffer);
}
/*
* put out a checksum record */
static void ieee_putcs(int toclear)
{
if (toclear) {
ieee_putascii("CS.\r\n");
} else {
checksum += 'C';
checksum += 'S';
ieee_putascii("CS%02X.\r\n", checksum & 127);
}
checksum = 0;
}
static long ieee_putld(long start, long end, unsigned char *buf)
{
long val;
if (start == end)
return (start);
val = start % HUNKSIZE;
/* fill up multiple lines */
while (end - start >= LDPERLINE) {
int i;
ieee_putascii("LD");
for (i = 0; i < LDPERLINE; i++) {
ieee_putascii("%02X", buf[val++]);
start++;
}
ieee_putascii(".\r\n");
}
/* if no partial lines */
if (start == end)
return (start);
/* make a partial line */
ieee_putascii("LD");
while (start < end) {
ieee_putascii("%02X", buf[val++]);
start++;
}
ieee_putascii(".\r\n");
return (start);
}
static long ieee_putlr(struct ieeeFixupp *p)
{
/*
* To deal with the vagaries of segmentation the LADsoft linker
* defines two types of segments: absolute and virtual. Note that
* 'absolute' in this context is a different thing from the IEEE
* definition of an absolute segment type, which is also supported. If a
* sement is linked in virtual mode the low limit (L-var) is
* subtracted from each R,X, and P variable which appears in an
* expression, so that we can have relative offsets. Meanwhile
* in the ABSOLUTE mode this subtraction is not done and
* so we can use absolute offsets from 0. In the LADsoft linker
* this configuration is not done in the assemblker source but in
* a source the linker reads. Generally this type of thing only
* becomes an issue if real mode code is used. A pure 32-bit linker could
* get away without defining the virtual mode...
*/
char buf[40];
long size = p->size;
switch (p->ftype) {
case FT_SEG:
if (p->id1 < 0)
sprintf(buf, "%lX", -p->id1);
else
sprintf(buf, "L%lX,10,/", p->id1);
break;
case FT_OFS:
sprintf(buf, "R%lX,%lX,+", p->id1, p->addend);
break;
case FT_REL:
sprintf(buf, "R%lX,%lX,+,P,-,%X,-", p->id1, p->addend, p->size);
break;
case FT_WRT:
if (p->id2 < 0)
sprintf(buf, "R%lX,%lX,+,L%lX,+,%lX,-", p->id2, p->addend,
p->id2, -p->id1 * 16);
else
sprintf(buf, "R%lX,%lX,+,L%lX,+,L%lX,-", p->id2, p->addend,
p->id2, p->id1);
break;
case FT_EXT:
sprintf(buf, "X%lX", p->id1);
break;
case FT_EXTREL:
sprintf(buf, "X%lX,P,-,%lX,-", p->id1, size);
break;
case FT_EXTSEG:
/* We needed a non-ieee hack here.
* We introduce the Y variable, which is the low
* limit of the native segment the extern resides in
*/
sprintf(buf, "Y%lX,10,/", p->id1);
break;
case FT_EXTWRT:
if (p->id2 < 0)
sprintf(buf, "X%lX,Y%lX,+,%lX,-", p->id2, p->id2,
-p->id1 * 16);
else
sprintf(buf, "X%lX,Y%lX,+,L%lX,-", p->id2, p->id2, p->id1);
break;
}
ieee_putascii("LR(%s,%lX).\r\n", buf, size);
return (size);
}
/* Dump all segment data (text and fixups )*/
static void ieee_unqualified_name(char *dest, char *source)
{
if (ieee_uppercase) {
while (*source)
*dest++ = toupper(*source++);
*dest = 0;
} else
strcpy(dest, source);
}
void dbgls_init(struct ofmt *of, void *id, FILE * fp, efunc error)
{
int tempint;
(void)of;
(void)id;
(void)fp;
(void)error;
fnhead = NULL;
fntail = &fnhead;
arrindex = ARRAY_BOT;
arrhead = NULL;
arrtail = &arrhead;
ieee_segment("??LINE", 2, &tempint);
any_segs = FALSE;
}
static void dbgls_cleanup(void)
{
struct ieeeSection *segtmp;
while (fnhead) {
struct FileName *fntemp = fnhead;
fnhead = fnhead->next;
nasm_free(fntemp->name);
nasm_free(fntemp);
}
for (segtmp = seghead; segtmp; segtmp = segtmp->next) {
while (segtmp->lochead) {
struct ieeePublic *loctmp = segtmp->lochead;
segtmp->lochead = loctmp->next;
nasm_free(loctmp->name);
nasm_free(loctmp);
}
}
while (arrhead) {
struct Array *arrtmp = arrhead;
arrhead = arrhead->next;
nasm_free(arrtmp);
}
}
/*
* because this routine is not bracketed in
* the main program, this routine will be called even if there
* is no request for debug info
* so, we have to make sure the ??LINE segment is avaialbe
* as the first segment when this debug format is selected
*/
static void dbgls_linnum(const char *lnfname, long lineno, long segto)
{
struct FileName *fn;
struct ieeeSection *seg;
int i = 0;
if (segto == NO_SEG)
return;
/*
* If `any_segs' is still FALSE, we must define a default
* segment.
*/
if (!any_segs) {
int tempint; /* ignored */
if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))
error(ERR_PANIC, "strange segment conditions in OBJ driver");
}
/*
* Find the segment we are targetting.
*/
for (seg = seghead; seg; seg = seg->next)
if (seg->index == segto)
break;
if (!seg)
error(ERR_PANIC, "lineno directed to nonexistent segment?");
for (fn = fnhead; fn; fn = fn->next) {
if (!nasm_stricmp(lnfname, fn->name))
break;
i++;
}
if (!fn) {
fn = nasm_malloc(sizeof(*fn));
fn->name = nasm_malloc(strlen(lnfname) + 1);
fn->index = i;
strcpy(fn->name, lnfname);
fn->next = NULL;
*fntail = fn;
fntail = &fn->next;
}
ieee_write_byte(seghead, fn->index);
ieee_write_word(seghead, lineno);
ieee_write_fixup(segto, NO_SEG, seghead, 4, OUT_ADDRESS,
seg->currentpos);
}
static void dbgls_deflabel(char *name, long segment,
long offset, int is_global, char *special)
{
struct ieeeSection *seg;
int used_special; /* have we used the special text? */
/* Keep compiler from warning about special and used_special */
used_special = special ? FALSE : FALSE;
/*
* If it's a special-retry from pass two, discard it.
*/
if (is_global == 3)
return;
/*
* First check for the double-period, signifying something
* unusual.
*/
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
return;
}
/*
* Case (i):
*/
if (ieee_seg_needs_update)
return;
if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
return;
if (segment >= SEG_ABS || segment == NO_SEG) {
return;
}
/*
* If `any_segs' is still FALSE, we might need to define a
* default segment, if they're trying to declare a label in
* `first_seg'. But the label should exist due to a prior
* call to ieee_deflabel so we can skip that.
*/
for (seg = seghead; seg; seg = seg->next)
if (seg->index == segment) {
struct ieeePublic *loc;
/*
* Case (ii). Maybe MODPUB someday?
*/
if (!is_global) {
last_defined = loc = nasm_malloc(sizeof(*loc));
*seg->loctail = loc;
seg->loctail = &loc->next;
loc->next = NULL;
loc->name = nasm_strdup(name);
loc->offset = offset;
loc->segment = -1;
loc->index = seg->ieee_index;
}
}
}
static void dbgls_typevalue(long type)
{
int elem = TYM_ELEMENTS(type);
type = TYM_TYPE(type);
if (!last_defined)
return;
switch (type) {
case TY_BYTE:
last_defined->type = 1; /* unsigned char */
break;
case TY_WORD:
last_defined->type = 3; /* unsigned word */
break;
case TY_DWORD:
last_defined->type = 5; /* unsigned dword */
break;
case TY_FLOAT:
last_defined->type = 9; /* float */
break;
case TY_QWORD:
last_defined->type = 10; /* qword */
break;
case TY_TBYTE:
last_defined->type = 11; /* TBYTE */
break;
default:
last_defined->type = 0x10; /* near label */
break;
}
if (elem > 1) {
struct Array *arrtmp = nasm_malloc(sizeof(*arrtmp));
int vtype = last_defined->type;
arrtmp->size = elem;
arrtmp->basetype = vtype;
arrtmp->next = NULL;
last_defined->type = arrindex++ + 0x100;
*arrtail = arrtmp;
arrtail = &(arrtmp->next);
}
last_defined = NULL;
}
static void dbgls_output(int output_type, void *param)
{
(void)output_type;
(void)param;
}
static struct dfmt ladsoft_debug_form = {
"LADsoft Debug Records",
"ladsoft",
dbgls_init,
dbgls_linnum,
dbgls_deflabel,
null_debug_routine,
dbgls_typevalue,
dbgls_output,
dbgls_cleanup,
};
static struct dfmt *ladsoft_debug_arr[3] = {
&ladsoft_debug_form,
&null_debug_form,
NULL
};
struct ofmt of_ieee = {
"IEEE-695 (LADsoft variant) object file format",
"ieee",
NULL,
ladsoft_debug_arr,
&null_debug_form,
NULL,
ieee_init,
ieee_set_info,
ieee_out,
ieee_deflabel,
ieee_segment,
ieee_segbase,
ieee_directive,
ieee_filename,
ieee_cleanup
};
#endif /* OF_IEEE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -