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

📄 outasm.c

📁 用C++编写的一个编译器
💻 C
字号:
#include <stdio.h>
#include "utility.h"
#include "genasm.h"

//the same order as enum en_opcode
char *optab[]={
	"mov",	"movsx","movzx","push",	"pop",	"lea",	"xchg",
	"add",	"sub",	"inc",	"dec",	"neg",	"cmp",
	"jmp",	"jz",	"jnz",	
	"jg",	"jge",	"jl",	"jle",
	"ja",	"jae",	"jb",	"jbe",
	"imul",	"idiv",	"mul",	"div",	"cdq",	//sign extension
	"and",	"or",	"xor",	"not",	"test",	//bit calc
	"sal",	"shl",	"sar",	"shr",	"call", "",
	"cld",	"rep",	"movsb"
};

void put_pointer(int size)
{
	switch (size) {
	case 10:
		printf("tword ");
		break;
	case 8: 
		printf("qword ");
		break;
	case 6:
		printf("fword ");
		break;
	case 4:                      
		printf("dword ");
		break;
	case 2:
		printf("word ");
		break;
	case 1:
		printf("byte ");
		break;
	default:
		debug("Bad pointer");
	}	
	printf("ptr ");
	return ;
}
void put_opcode(int opcode)
{
	printf("%-12s", optab[opcode]);
	return ;
}
//remember register no from 1 to 8
void put_reg(int reg, int size)
{
	static char *regname[4][8]={
	{ "al","cl","dl","bl","ah","ch","dh","bh" },
	{ "ax", "cx", "dx","bx","si","di","sp","bp"  },
	{0},
	{ "eax", "ecx", "edx","ebx","esi","edi","esp","ebp" }};
	printf(regname[--size][reg]);
	return ;
}

void put_addrmode(AddrMode *am)
{
	switch(am->mode)
	{
	case am_label:
		if(am->entry)
			printf("%s ", am->entry);
		else 
			printf("_lb_%ld ", am->offset);
		break;
	case am_imme:
		if(am->entry)//const pointer offset
		{
			printf("offset %s ", am->entry);
			if(am->offset>0)
				printf(" + 0%lxh", am->offset);
			else if(am->offset<0)
				printf(" - 0%lxh", -am->offset);
		}
		else 
		{
			printf("0%lxh ", am->offset);
		}
		break;
	case am_dreg:
		put_reg(am->base_reg, am->size);
		break;
	case am_freg:
		printf("ST(%d)", am->base_reg);
		break;
	case am_direct:
		put_pointer(am->size);
		if(am->entry)//const pointer offset
		{
			printf("[ %s ", am->entry);
			if(am->offset>0)
				printf(" + 0%lxh", am->offset);
			else if(am->offset<0)
				printf(" - 0%lxh", -am->offset);
			putchar(']');
		}
		break;
	case am_relative:
		put_pointer(am->size);
		putchar('[');
		put_reg(am->base_reg, 4);
		if(am->offset>0)
			printf(" + 0%lxh", am->offset);
		else if(am->offset<0)
			printf(" - 0%lxh", -am->offset);
		putchar(']');
		break;
	case am_scale:
		put_pointer(am->size);
		putchar('[');
		put_reg(am->base_reg, 4);
		if(am->index_reg!=UNKNOWN)
		{
			if(am->scale>1)
				printf(" + 0%x*", am->scale);
			else
				printf(" + ", am->scale);
			put_reg(am->index_reg, 4);
		}
		if(am->offset>0)
			printf(" + 0%lxh", am->offset);
		else if(am->offset<0)
			printf(" - 0%lxh", -am->offset);//???????need check
		putchar(']');
		break;
	default:
		debug("Unknown address mode");
	}
	return ;
}

/*
The main routine of generate asm code
output a instruct
*/
void put_outcode(OutCode *oc)
{
	if(oc->opcode == op_label)
	{
		printf("_lb_%ld:\n", (long)oc->opd1);
		return;
	}
		
	if(oc->opcode == op_rep)
	{
		printf("\trep");
		return;
	}
	putchar('\t');
	put_opcode(oc->opcode);
	if(oc->opcode == op_call && oc->opd1->mode==am_imme)
	{
		puts(oc->opd1->entry);//an ugly patch...
		return ;
	}
	if(oc->opd1)
	{
		put_addrmode(oc->opd1);
		if(oc->opd2)
		{
			printf(", ");
			put_addrmode(oc->opd2);
		}
	}
	putchar('\n');
	return ;
}
/*
 Output	the header content of the asm file 
*/
void asm_header(void)
{
	printf("\
.386p\n\
.model flat\n\n\n\
.code\n");
	return;
}

void asm_func_begin(
	char *func_name,
	long localdata
)
{
	printf("\
%-10s  proc\n\
	push		ebp\n\
	mov 		ebp, esp\n", func_name);
	
	if(localdata>0)printf("\
	sub 		esp, 0%lxh\n", localdata);
	
	printf("\
	push		ebx\n\
	push		esi\n\
	push		edi\n");
	
	return ;
}

void asm_func_end(
	char *func_name
)
{
	printf("\
	pop			edi\n\
	pop			esi\n\
	pop			ebx\n\
	mov			esp, ebp\n\
	pop			ebp\n\
	ret\n\
%-10s  endp\n", func_name);
	
	return ;
}

/*
Output the global variables and const string,
including data segment and bss segment
*/

void asm_globaldata(void)
{
	char *str, ch;
	Symbol *sym;
	printf("\
.const\n\
string	label byte\n");
	while(str = popfront_List(&const_list))
	{
		int in=false;
		printf("\tdb\t");
		while(ch=*str++)
		{
			if(ch<32)
			{
				if(in)
				{
					printf("\",0%xh,", ch);
					in=false;
				}
				else 
					printf("0%xh,", ch);
			}
			else 
			{
				if(!in)
				{
					in=true;
					printf("\"%c",ch);
				}
				else 
					putchar(ch);
			}
		}
		if(in)printf("\",00h\n");
		else printf("00h\n");
	}
	printf("\
.data\n");
	while(sym= popfront_List(&data_list))
	{
		long i=1, size = sym->datatype->size;
		char *data=sym->init;
		printf("%-6s  db 0%lxh 0%xh", 
			sym->value.linkname, size, *data);
		for(;i<size;i++)
			printf(",0%xh", data[i]);
		putchar('\n');
	}
	printf("\
.data?\n");
	while(sym= popfront_List(&bss_list))
	{
		if(sym->datatype->size>1)printf("%-6s  db 0%lxh dup(?)\n", 
			sym->value.linkname, sym->datatype->size);
		else printf("%-6s  db ?\n", 
			sym->value.linkname, sym->datatype->size);
	}
	return ;
}
/*
* Output the fixup tables and the global/external list
*/
void asm_externdecl(void)
{
	Symbol *sym;
	while(sym= popfront_List(&extern_list))
	{
		if(sym->storage_class == sc_external)
		{
			if(sym->refcount<=0)
				continue;
			if(sym->datatype->basic_type == bt_funcptr
				&&sym->const_flag)
			{
				printf("extrn %s:proc\n", sym->name);
			}
			else 
				printf("extrn %s:byte\n", sym->value.linkname);
		}
		else if(sym->storage_class == sc_global)
			printf("public %s\n", sym->name);
	}
	printf("end\n");
}

⌨️ 快捷键说明

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