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

📄 nasm.c

📁 unix环境下实现的cmm语言编译器
💻 C
字号:
#include "cmm.h"enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };static Symbol charreg[8], shortreg[8], intreg[8];static Symbol quo, rem; /*quo为'/'运算分配的寄存器,rem为'%'分配的寄存器*/static int cseg;		/* current segment */static void progbeg(void){	intreg[EAX] = mkreg("eax", EAX);	intreg[EDX] = mkreg("edx", EDX);	intreg[ECX] = mkreg("ecx", ECX);	intreg[EBX] = mkreg("ebx", EBX);	intreg[ESI] = mkreg("esi", ESI);	intreg[EDI] = mkreg("edi", EDI);	shortreg[EAX] = mkreg("ax", EAX);	shortreg[ECX] = mkreg("cx", ECX);	shortreg[EDX] = mkreg("dx", EDX);	shortreg[EBX] = mkreg("bx", EBX);	shortreg[ESI] = mkreg("si", ESI);	shortreg[EDI] = mkreg("di", EDI);	charreg[EAX]  = mkreg("al", EAX);	charreg[ECX]  = mkreg("cl", ECX);	charreg[EDX]  = mkreg("dl", EDX);	charreg[EBX]  = mkreg("bl", EBX);	rmap[C] = mkwildcard(charreg);	rmap[P]  = rmap[U] = rmap[I] = rmap[A] = mkwildcard(intreg);	quo = mkreg("eax", EAX);	quo->x.regnode->mask |= 1<<EDX;	rem = mkreg("edx", EDX);	rem->x.regnode->mask |= 1<<EAX;}static void emit2(Node p){#define preg(f) ((f)[getregnum(p->kids[0])]->x.name)	if (p->op == CVCI)		print("movsx %s,%s\n", p->syms[RX]->x.name			, preg(charreg));	else if (p->op == CVIC ) {		char *dst = shortreg[getregnum(p)]->x.name;		char *src = preg(shortreg);		if (dst != src)			print("mov %s,%s\n", dst, src);	}}static void function(Symbol f, Symbol caller[], Symbol callee[]){	int i;	DEBUG(fprint(2,"function define start\n"));	print("%s:\n", f->x.name);	print("push ebx\n");	print("push edx\n");	print("push ecx\n");	print("push esi\n");	print("push edi\n");	print("push ebp\n");	print("mov ebp,esp\n");	freemask = ~(unsigned)0;	reg_var_count  = 0;	offset = 24 + 4;	for (i = 0; callee[i]; i++) {		Symbol p = callee[i];		Symbol q = caller[i];		assert(q);		p->x.offset = q->x.offset = offset;		p->x.name = q->x.name = stringf("%d", p->x.offset);		p->sclass = q->sclass = AUTO;		offset += roundup(q->type->size, 4);	}	assert(caller[i] == 0);	offset = maxoffset = 0;	gencode(caller, callee);	print("mov esp,ebp\n");	print("pop ebp\n");	print("pop edi\n");	print("pop esi\n");	print("pop ecx\n");	print("pop edx\n");	print("pop ebx\n");	print("ret\n");	DEBUG(fprint(2,"function define end\n"));}static void progend(){}static void defsymbol(Symbol p){	if (p->generated)		p->x.name = stringf("L%s", p->name);	else if (p->scope == CONSTANT	&& isptr(p->type))		p->x.name = stringf("%d", p->u.c.v.u);	else		p->x.name = p->name;}/*target为p选择寄存器*/static void target(Node p){	assert(p);	switch(p->op) {	case DIVI: /*商在eax,余数在edx,*/		setreg(p, quo);		rtarget(p, 0, intreg[EAX]); /*被除数放在eax*/		rtarget(p, 1, intreg[ECX]); /*除数放在ecx*/		break;	case MODI:		setreg(p, rem);		rtarget(p, 0, intreg[EAX]);		rtarget(p, 1, intreg[ECX]);		break;			case ASGNA: /*局部数组的初始化时生成的赋值,将通过movsb指令进行实现*/		setreg(p, intreg[ECX]);		/*ecx做为传送数据的计数器*/		rtarget(p, 0, intreg[EDI]); /*edi做为目标寄存器*/		rtarget(p, 1, intreg[ESI]); /*esi做为源寄存器*/		break;	case CALLI: case CALLV: case CALL + P:		setreg(p, intreg[EAX]); /*函数的返回值放在eax*/		break;	case RETI:		rtarget(p, 0, intreg[EAX]); /*返回值放在eax*/		break;	}}static void doarg(Node p){	assert(p && p->syms[0]);	mkactual(4, p->syms[0]->u.c.v.i);}static void segment(int n);static void import(Symbol p){	int oldseg = cseg;	if (p->ref > 0) {		segment(CODE);		print("extern %s\n", p->x.name);		segment(oldseg);	}}static void space(int n){	if (cseg != BSS)		print("resb %d \n", n);}static void segment(int n){	if (n == cseg)        return;    cseg = n;    if (CODE == cseg)        print("section .text\n");    else if (DATA == cseg || BSS == cseg)        print("section .data\n");}static void local(Symbol p){	if (0 == askregvar(p, rmap[ttob(p->type)]))		mkauto(p);}static void global(Symbol p){	print("align %d\n",		p->type->align > 4 ? 4 : p->type->align);	print("%s:\n", p->x.name);	if (BSS == p->u.seg)		print("resb %d\n", p->type->size);}static void defconst(int ty,Value v){	switch (ty) {		case C: print("db %d\n",   v.c); return;		case I: print("dd %d\n",   v.i ); return;		case P: print("dd 0%xH\n", v.p ); return;	}	assert(0);}/*def_array_end:设置字符数组结束的标志'\0'*/void def_array_end(void){	Value v;	v.c = 0;	defconst(C, v);}void set_eax(Node p){	p->syms[RX] = intreg[EAX];}void set_edx(Node p){	p->syms[RX] = intreg[EDX];}void put_eax(void){	freemask |= intreg[EAX]->x.regnode->mask;}/*putreg:释放寄存器*/void putreg(Symbol r){	if (r == quo)	/*edx已经在之前被释放*/		r = intreg[EAX];	if (r == rem)	/*edx已经在之前被释放*/		r = intreg[EDX];	freemask |= r->x.regnode->mask;	}void put_edx(void){	freemask |= intreg[EDX]->x.regnode->mask;}int equal_reg(Node p, Node kid){	assert(p && kid);	Symbol ra = p->syms[RX], rb = kid->syms[RX];    if (ra == rb)        return 1;    if ((ra == quo || ra == intreg[EAX])    && (rb == quo || rb == intreg[EAX]))        return 1;    if ((ra == rem || ra == intreg[EDX])    && (rb == rem || rb == intreg[EDX]))        return 1;    return 0;}static void defstring(int n, char *str){	char *s;	for (s = str; s < str + n; s++)		print("db %d\n", (*s)&0377);	print("db 0\n");}static void defaddress(Symbol p){	print("dd %s\n", p->x.name);}/*export引出全局的变量*/static void export(Symbol p){	print("global %s\n",p->x.name);}Interface x86IR = {	blockbeg,	blockend,	defaddress,	defconst,	defstring,	defsymbol,	export,	function,	gen,	global,	import,	local,	progbeg,	progend,	segment,	space,	{ 	emit2,	    doarg,	    target,	}};

⌨️ 快捷键说明

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