⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outco386.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 5 页
字号:
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_stc[] = 
{
    {
        OP_CODEONLY, 0x00f9, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_std[] = 
{
    {
        OP_CODEONLY, 0x00fd, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_sti[] = 
{
    {
        OP_CODEONLY, 0x00fb, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_stos[] = 
{
    {
        OP_STOS, 0x00ab, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_stosb[] = 
{
    {
        OP_CODEONLY, 0x00aa, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_stosd[] = 
{
    {
        OP_INSDWORDSIZE, 0x00ab, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_stosw[] = 
{
    {
        OP_INSWORDSIZE, 0x00ab, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_str[] = 
{
    {
        OP_NOSTRICTRM, 0x0800, 0x0a03
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_sub[] = 
{
    {
        OP_RMIMMSIGNED, 0x2880, 0x0200
    }
    , 
    {
        OP_ACCIMM, 0x002c, 0x0000
    }
    , 
    {
        OP_REGRMREG, 0x0028, 0x0200
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_test[] = 
{
    {
        OP_ACCIMM, 0x00a8, 0x0000
    }
    , 
    {
        OP_REGMOD, 0x0084, 0x0200
    }
    , 
    {
        OP_RMIMM, 0x00f6, 0x0200
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_ud2[] = 
{
    {
        OP_CODEONLY, 0x000b, 0x0806
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_verr[] = 
{
    {
        OP_NOSTRICTRM, 0x2000, 0x0a02
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_verw[] = 
{
    {
        OP_NOSTRICTRM, 0x2800, 0x0a02
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_wait[] = 
{
    {
        OP_CODEONLY, 0x009b, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_wbinvd[] = 
{
    {
        OP_CODEONLY, 0x0009, 0x0904
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_wrmsr[] = 
{
    {
        OP_CODEONLY, 0x0030, 0x0905
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xadd[] = 
{
    {
        OP_BYTERMREG, 0x00c0, 0x0a04
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xbts[] = 
{
    {
        OP_CODEONLY, 0x00a6, 0x0803
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xchg[] = 
{
    {
        OP_ACCREG02, 0x0090, 0x0000
    }
    , 
    {
        OP_REGRM, 0x0086, 0x0200
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xlat[] = 
{
    {
        OP_CODEONLY, 0x00d7, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xlatb[] = 
{
    {
        OP_CODEONLY, 0x00d7, 0x0000
    }
    , 
    {
        0, 0, 0
    }
    , 
};
OPCODE popn_xor[] = 
{
    {
        OP_RMIMMSIGNED, 0x3080, 0x0200
    }
    , 
    {
        OP_ACCIMM, 0x0034, 0x0000
    }
    , 
    {
        OP_REGRMREG, 0x0030, 0x0200
    }
    , 
    {
        0, 0, 0
    }
    , 
};
void outcode_file_init(void)
{
    int i;
    labelbuf = xalloc(400 *sizeof(LABEL*));

    for (i = 0; i < MAX_SEGS; i++)
        memset(&segs[i], 0, sizeof(segs[i]));
    linelist = 0;
    virtualFirst = virtualLast = 0;

}

//-------------------------------------------------------------------------

void outcode_func_init(void)
{
    int i;
    //   memset(labelbuf,0,400 * sizeof(LABEL *)) ;

    for (i = 0; i < MAX_SEGS; i++)
        segs[i].curbase = segs[i].curlast;

    if (currentfunc)
        if (curseg == virtseg)
            currentfunc->mainsym->offset = outcode_base_address = 0;
        else
            currentfunc->mainsym->offset = outcode_base_address =
                segs[codeseg].curbase;
}

//-------------------------------------------------------------------------

void InsertLabel(int lbl, int address, int seg)
{
    int x = lbl / 512;
    if (!labelbuf[x])
    {
        global_flag++;
        labelbuf[x] = xalloc(512 *sizeof(LABEL));
        global_flag--;
    }
    labelbuf[x][lbl % 512].address = address;
    labelbuf[x][lbl % 512].seg = seg;
}

//-------------------------------------------------------------------------

int LabelAddress(int lbl)
{
    if (labelbuf)
    {
        LABEL *p = labelbuf[lbl / 512];
        if (p)
        {
            //	  	 printf("addr %x\n",p[lbl%412].address) ;
            return p[lbl % 512].address;
        }
    }
    DIAG("LabelAddress - missing label");
    return 0;
    //   return labelbuf[lbl/512][lbl%512].address ;
}

//-------------------------------------------------------------------------

int LabelSeg(int lbl)
{
    return labelbuf[lbl / 512][lbl % 512].seg;
}

//-------------------------------------------------------------------------

void InsertLine(int address, int line, int file)
{
    LINEBUF *l;
    global_flag++;
    l = xalloc(sizeof(LINEBUF));
    global_flag--;
    l->address = address;
    l->lineno = line;
    l->file = file;
    if (linelist)
        linetail = linetail->next = l;
    else
        linelist = linetail = l;
}

//-------------------------------------------------------------------------

EMIT_TAB *gettab(int seg)
{
    if (seg == virtseg)
        return virtualLast->seg;
    else
    {
        EMIT_TAB *rv = &segs[seg];
        if (!rv->first)
        {
            global_flag++;
            rv->first = rv->last = xalloc(sizeof(EMIT_LIST));
            global_flag--;
        }
        return rv;
    }
}

//-------------------------------------------------------------------------

void emit(int seg, BYTE *data, int len)
{
    EMIT_TAB *tab = gettab(seg);
    int ofs = 0;
    if (!tab->first)
    {
        global_flag++;
        tab->first = tab->last = xalloc(sizeof(EMIT_LIST));
        global_flag--;
    }
    tab->last->lastfilled = tab->last->filled;
    tab->curlast += len;
    while (len)
    {
        int size = len >= 1024 ? 1024 : len;
        if (tab->last->filled + len > 1024)
        {
            int address = tab->last->address + tab->last->filled;
            global_flag++;
            tab->last = tab->last->next = xalloc(sizeof(EMIT_LIST));
            tab->last->address = address;
            global_flag++;
        }

        memcpy(tab->last->data + tab->last->filled, data + ofs, size);
        tab->last->filled += size;
        len -= size;
        ofs += size;
    }
}

//-------------------------------------------------------------------------

void write_to_seg(int seg, int offset, char *value, int len)
{
    EMIT_TAB *tab = gettab(seg);
    EMIT_LIST *lst = tab->first;
    while (lst->address + lst->filled < offset)
        lst = lst->next;
    memcpy(lst->data + offset - lst->address, value, len);
}

//-------------------------------------------------------------------------

void gen_symbol_fixup(enum mode xmode, int seg, int address, SYM *pub)
{
    FIXUP *fixup;
    EMIT_TAB *tab = gettab(seg);
    global_flag++;
    fixup = xalloc(sizeof(FIXUP));
    global_flag--;
    fixup->fmode = xmode;
    fixup->address = address;
    fixup->sym = pub;
    if (tab->last->fixups)
        tab->last->lastfixup = tab->last->lastfixup->next = fixup;
    else
        tab->last->fixups = tab->last->lastfixup = fixup;

} void gen_label_fixup(enum mode xmode, int seg, int address, int lab)
{
    FIXUP *fixup;
    EMIT_TAB *tab = gettab(seg);
    global_flag++;
    fixup = xalloc(sizeof(FIXUP));
    global_flag--;
    fixup->fmode = xmode;
    fixup->address = address;
    fixup->label = lab;
    if (tab->last->fixups)
        tab->last->lastfixup = tab->last->lastfixup->next = fixup;
    else
        tab->last->fixups = tab->last->lastfixup = fixup;

} void outcode_dump_muldivval(void)
{
    MULDIV *v = muldivlink;
    unsigned char buf[10];
    while (v)
    {
        InsertLabel(v->label, segs[curseg].curlast, curseg);
        if (v->size == 0)
        {
            *(int*)buf = v->value;
            emit(curseg, buf, 4);
        }
        else if (v->size == 7 || v->size == 15)
        {
            *(float*)buf = v->floatvalue;
            emit(curseg, buf, 4);
        }
        else if (v->size == 8 || v->size == 16)
        {
            *(double*)buf = v->floatvalue;
            emit(curseg, buf, 8);
        }
        else
        {
            *(long double*)buf = v->floatvalue;
            emit(curseg, buf, 10);
        }
        v = v->link;
    }
}

//-------------------------------------------------------------------------

void outcode_dump_browsedata(unsigned char *buf, int len)
{
    emit(browseseg, buf, len);
}

//-------------------------------------------------------------------------

void outcode_dumplits(void)
{
    struct slit *v = strtab;
    int val = 0;
    xstringseg();
    while (v != 0)
    {
        InsertLabel(v->label, segs[stringseg].curlast, stringseg);
        emit(curseg, v->str, v->len - 1);

        if (v->type)
            emit(curseg, (unsigned char*) &val, 2);
        else
            emit(curseg, (unsigned char*) &val, 1);
        v = v->next;
    } nl();
}

//-------------------------------------------------------------------------

void outcode_genref(SYM *sp, int offset)
{
    EMIT_TAB *seg = gettab(curseg);
    emit(curseg, &offset, 4);

    gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
        ->lastfilled, sp);
}

//-------------------------------------------------------------------------

void outcode_gen_labref(int n)
{
    int i = 0;
    EMIT_TAB *seg = gettab(curseg);
    emit(curseg, &i, 4);
    gen_label_fixup(fm_label, curseg, seg->last->address + seg->last
        ->lastfilled, n);
}

/* the labels will already be resolved well enough by this point */
void outcode_gen_labdifref(int n1, int n2)
{
    int i = LabelAddress(n1) - LabelAddress(n2);
    EMIT_TAB *seg = gettab(curseg);
    emit(curseg, &i, 4);
}

//-------------------------------------------------------------------------

void outcode_gensrref(SYM *sp, int val)
{
    char buf[8];
    EMIT_TAB *seg = gettab(curseg);
    memset(buf, 0, 8);
    *(int*)(buf + 4) = val;
    emit(curseg, buf, 8);
    gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
        ->lastfilled, sp);
}

//-------------------------------------------------------------------------

void outcode_genstorage(int len)
{
    char buf[256];
    memset(buf, 0, 256);
    while (len >= 256)
    {
        emit(curseg, buf, 256);
        len -= 256;
    }
    if (len)
        emit(curseg, buf, len);
}

//-------------------------------------------------------------------------

void outcode_genfloat(long double val)
{
    float f = val;
    emit(curseg, &f, 4);
}

//-------------------------------------------------------------------------

void outcode_gendouble(long double val)
{
    double d = val;
    emit(curseg, &d, 8);
}

//-------------------------------------------------------------------------

void outcode_genlongdouble(long double val)
{
    emit(curseg, &val, 10);
}

//-------------------------------------------------------------------------

void outcode_genstring(char *string, int len)
{
    emit(curseg, string, len);
}

//-------------------------------------------------------------------------

void outcode_genbyte(int val)
{
    emit(curseg, &val, 1);
}

//-------------------------------------------------------------------------

void outcode_genword(int val)
{
    emit(curseg, &val, 2);
}

//-------------------------------------------------------------------------

void outcode_genlong(int val)
{
    emit(curseg, &val, 4);
}

//-------------------------------------------------------------------------

void outcode_genlonglong(LLONG_TYPE val)
{
    emit(curseg, &val, 4);
    #ifdef BCC32
        val = val < 0 ?  - 1: 0;
    #else 
        val = val >> 32;
    #endif 
    emit(curseg, &val, 4);
}

//-------------------------------------------------------------------------

void outcode_align(int size)
{
    EMIT_TAB *seg = gettab(curseg);
    int adr = seg->last->address + seg->last->filled;
    adr = size - adr % size;
    if (size != adr)
        outcode_genstorage(adr);
}

//-------------------------------------------------------------------------

void outcode_put_label(int lab)
{
    EMIT_TAB *seg = gettab(curseg);
    InsertLabel(lab, seg->last->address + seg->last->filled, curseg);
}

//-------------------------------------------------------------------------

void outcode_start_virtual_seg(SYM *sp, int data)
{
    VIRTUAL_LIST *x;
    global_flag++;
    x = xalloc(sizeof(VIRTUAL_LIST));
    x->sp = sp;
    x->seg = xalloc(sizeof(EMIT_TAB));
    x->data = data;
    global_flag--;
    if (virtualFirst)
        virtualLast = virtualLast->next = x;
    else
        virtualFirst = virtualLast = x;
}

//-------------------------------------------------------------------------

void outcode_end_virtual_seg(SYM *sp){}
ENODE *GetSymRef(ENODE *n)
{
    ENODE *rv;
    switch (n->nodetype)
    {
        case en_add:
        case en_addstruc:
            if (rv = GetSymRef(n->v.p[0]))
                break;
            rv = GetSymRef(n->v.p[1]);
            break;
        case en_icon:
        case en_boolcon:
        case en_ccon:
        case en_cucon:
        case en_lcon:
        case en_lucon:
        case en_iucon:
            return 0;
        case en_labcon:
        case en_nacon:
        case en_autocon:
        case en_absacon:
        case en_nalabcon:
        case en_napccon:
            return n;
        default:
            DIAG("Unexpected node type in GetSymRef");
            break;
    }
    return rv;
}

//-------------------------------------------------------------------------

int resolveoffset(OCODE *ins, ENODE *n, int *resolved)
{
    int rv = 0;
    if (n)
    {
        switch (n->nodetype)
        {
            case en_add:
            case en_addstruc:
                rv += resolveoffset(ins, n->v.p[0], resolved);
                rv += resolveoffset(ins, n->v.p[1], resolved);
                break;
            case en_llcon:
            case en_llucon:
            case en_icon:
            case en_ccon:
            case en_cucon:
            case en_lcon:
            case en_lucon:
            case en_iucon:
            case en_absacon:
            case en_boolcon:
                rv += n->v.i;
                break;
            case en_autocon:
            case en_autoreg:
                break;
            case en_labcon:
            case en_nacon:
            case en_nalabcon:
            case en_napccon:
                *resolved = 0;
                break;
            default:
                DIAG("Unexpected node type in resolveoffset");
                break;
        }
    }
    return rv;
}

//-------------------------------------------------------------------------

int asmrm(int reg, OCODE *ins, AMODE *data, BYTE **p)
{
    int resolved = 1, val;
    BYTE *rm;
    if (data->mode == am_dreg)
    {
        reg |= 0xc0 + data->preg;
        *(*p)++ = reg;
        return 1;
    }
    rm =  *p;
    if (data == ins->oper2)
    {
        ins->resobyte = 1;
    }
    switch (data->mode)
    {
        case am_indisp:
            indisp: if (data->preg == EBP)
            {
                *(*p)++ = 5 | reg;
                ins->addroffset =  *p - ins->outbuf;
                val = resolveoffset(ins, data->offset, &resolved);
                ins->resolved = resolved;
            }
            else if (data->preg == ESP)
            {
                *(*p)++ = 4+reg;
                *(*p)++ = 0x24;
                ins->addroffset =  *p - ins->outbuf;
                val = resolveoffset(ins, data->offset, &resolved);
                ins->resolved = resolved;
                #ifdef FULLVERSION
                    if (resolved &!val)
                        return 1;
                #endif 
            }
            else
            {
                *(*p)++ = reg + data->preg;
                ins->addroffset =  *p - ins->outbuf;
                val = resolveoffset(ins, data->offset, &resolved);
                ins->resolved = resolved;
                #ifdef FULLVERSION
                    if (resolved && !val)
                        return 1;
                #endif 
            }
            break;
        case am_indispscale:
            if (data->sreg ==  - 1)
                goto indisp;
            if (data->preg ==  - 1)
            {
                *(*p)++ = 0x04 + reg;
                *(*p)++ = 5+(data->sreg << 3) + (data->scale << 6);
                ins->addroffset =  *p - ins->outbuf;
                *((int*)(*p))++ = resolveoffset(ins, data->offset, &resolved);
                ins->resolved = resolved;
                return 1;
            }
            else
            {
                if (data->sreg == ESP || data->sreg == data->preg && data->sreg
                    == EBP)
                    return 0;
                if (data->preg != EBP)
                {
                    *(*p)++ = 4+reg;
                    *(*p)++ = data->preg + (data->sreg << 3) + (data->scale <<
                        6);
                    ins->addroffset =  *p - ins->outbuf;
                    val = resolveoffset(ins, data->offset, &resolved);
                    #ifdef FULLVERSION
                        if (!val && resolved)
                            return 1;
                    #endif 
                }
                else
                {
                    *(*p)++ = 4+reg;
                    *(*p)++ = 5+(data->sreg << 3) + (data->scale << 6);
                    ins->addroffset =  *p - ins->outbuf;
                    val = resolveoffset(ins, data->offset, &resolved);
                    ins->resolved = resolved;
                }
            }
            break;
        case am_direct:
            *(*p)++ = 5 | reg;
            ins->addroffset =  *p - ins->outbuf;
            *((int*)(*p))++ = resolveoffset(ins, data->offset, &resolved);
            ins->resolved = resolved;
            return 1;

        default:
            return 0;
    }
    if (resolved)
    {
        #ifdef FULLVERSION
            if (val >=  - 128 && val < 128)
            {

                *rm |= 0x40;
                *(*p)++ = val;
            }
            else
        #endif 
        {
            *rm |= 0x80;
            *((int*)(*p))++ = val;
        }
    }
    else
    {
        *rm |= 0x80;
        *((int*)(*p))++ = val;
    }
    ins->resolved = resolved;
    return 1;
}

//-------------------------------------------------------------------------

int asmfrm(int reg, OCODE *ins, AMODE *data, BYTE **p)
{
    reg &= 0x38;
    if (data->mode == am_freg)
    {
        *(*p)++ = 0xc0 + reg + data->preg;
        return 1;
    }
    return asmrm(reg, ins, data, p);
}

/*
 * no operands. In this case, the opcode length is 1, so we go through this
 *	weird locution to rep mov a single byte out of the structure and
 *	into [di], wherever that points. Apparently it points into an opcode
 *	buffer somewhere. If the opcode length is greater than one, what
 *	happens?
 */
int AOP0(OPCODE *descript, OCODE *data, BYTE **p)
{
    if (data->oper1)
        return 0;
    if (descript->ocflags &OCtwobyte)
        *((short*)(*p))++ = descript->ocvalue;
    else
        *(*p)++ = descript->ocvalue;
    return 1;
}

/* 
 *  word reg, bits 0-2 of opcode = reg num
 */
int AOP1(OPCODE *descript, OCODE *data, BYTE **p)
{
    if (data->oper2)
        return 0;
    if (data->oper1->length > 5)
        return 0;
    if (data->oper1->length == 1 || data->oper1->l

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -