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

📄 asm.c

📁 计算机系统结构的讲义,浓缩了一本一千多页的书.真的是好东西.
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	while ((*p == ' ') || (*p == '\t')) {	    p++;	}	if ((*p == '\n') || (*p == 0)) {	    continue;	}	/*	 * If this isn't an assembler pseudo-op, just assemble the	 * instruction and move on.	 */	while ((*p == ' ') || (*p == '\t')) {	    p++;	}	if (*p == ';') {	    continue;	}	if (*p != '.') {	    int size, code[ASM_MAX_WORDS], result;	    infoPtr->dot = (infoPtr->dot + 3) & ~3;	    result = Asm_Assemble(machPtr, fileName, p, infoPtr->dot,		    line, infoPtr->flags & ASM_SIZE_ONLY, &size, code);	    if (result == TCL_OK  && !(infoPtr->flags & ASM_SIZE_ONLY)) {		result = StoreWords(machPtr, infoPtr->dot, code,                     machPtr->codeLine++, size);            sprintf(msg, "(0x%08x)  0x%08x  %s", infoPtr->dot, *code, line);            Tcl_SetVar(machPtr->interp, "msg", msg, TCL_GLOBAL_ONLY);            Tcl_VarEval(machPtr->interp, ".code.t insert end $msg",	         (char *)NULL);	    }	    infoPtr->dot += size*4;	    goto endOfLine;	}	/*	 * Handle an assembler pseudo-op.	 */	curToken = p;	for (i = 0, p++; (i < MAX_NAME_SIZE) && isalpha(*p); i++, p++) {	    pseudoOp[i] = *p;	}	if (i >= MAX_NAME_SIZE) {	    IndicateError(machPtr->interp, "pseudo-op name too long",		    line, curToken);	    goto endOfLine;	}	pseudoOp[i] = 0;	while ((*p == ' ') || (*p == '\t')) {	    p++;	}	if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "align") == 0)) {	    if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) {		IndicateError(machPtr->interp, machPtr->interp->result,			line, p);		goto endOfLine;	    }	    p = end;	    if (i == 0) {		machPtr->interp->result = "\".align 0\" not supported";		goto endOfLine;	    } else {		i = (1 << i) - 1;		infoPtr->dot = (infoPtr->dot + i) & ~i;	    }	} else if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "ascii") == 0)) {	    nullTerm = 0;	    /*	     * Read one or more ASCII strings from the input line.  Each	     * must be surrounded by quotes, and they must be separated	     * by commas.	     */	    doString:	    while (1) {		while ((*p == ' ') || (*p == '\t')) {		    p++;		}		if (*p != '"') {		    IndicateError(machPtr->interp,			    "missing \" at start of string", line, p);		    goto endOfLine;		}		p++;		i = Gp_PutString(machPtr, p, '"', infoPtr->dot, nullTerm, &end);		if (*end != '"') {		    IndicateError(machPtr->interp,			    "missing \" at end of string", line, end-1);		    goto endOfLine;		}		p = end+1;		infoPtr->dot += i;		while ((*p == ' ') || (*p == '\t')) {		    p++;		}		if (*p != ',') {		    break;		}		p++;	    }	} else if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "asciiz") == 0)) {	    nullTerm = 1;	    goto doString;	} else if ((pseudoOp[0] == 'b') && (strcmp(pseudoOp, "byte") == 0)) {	    while (1) {		curToken = p;		if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end)			!= TCL_OK) {		    IndicateError(machPtr->interp, machPtr->interp->result,			    line, p);		    goto endOfLine;		}		Gp_PutByte(machPtr, infoPtr->dot, i);		infoPtr->dot += 1;		for (p = end; (*p == ' ') || (*p == '\t'); p++) {		    /* Null body;  just skip space. */		}		if (*p != ',') {		    break;		}		p++;	    }	} else if ((pseudoOp[0] == 'd') && (strcmp(pseudoOp, "data") == 0)) {	    if (infoPtr->flags & ASM_CODE) {		infoPtr->codeAddr = infoPtr->dot;	    } else {		infoPtr->dataAddr = infoPtr->dot;	    }	    if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) {		Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC);	    } else {		p = end;		infoPtr->dataAddr = i;	    }	    infoPtr->dot = infoPtr->dataAddr;	    infoPtr->flags &= ~ASM_CODE;	} else if ((pseudoOp[0] == 'g') && (strcmp(pseudoOp, "global") == 0)) {	    if (!isalpha(*p) && (*p != '_')) {		IndicateError(machPtr->interp,			"symbol name must start with letter or '_'", line, p);		goto endOfLine;	    }	    curToken = p;	    while (isalnum(*p) || (*p == '_') || (*p == '$')) {		p++;	    }	    savedChar = *p;	    *p = 0;	    if (infoPtr->flags & ASM_SIZE_ONLY) {		Sym_AddSymbol(machPtr, fileName, curToken, 0,			SYM_GLOBAL|SYM_NO_ADDR);		if (*machPtr->interp->result != 0) {		    AddErrMsg(machPtr->interp, infoPtr, 1);		}	    }	    *p = savedChar;	} else if ((pseudoOp[0] == 's') && (strcmp(pseudoOp, "space") == 0)) {	    if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) {		IndicateError(machPtr->interp, machPtr->interp->result,			line, p);		goto endOfLine;	    }	    p = end;	    while (i > 0) {		Gp_PutByte(machPtr, infoPtr->dot, 0);		infoPtr->dot += 1;		i -= 1;	    }	} else if ((pseudoOp[0] == 't') && (strcmp(pseudoOp, "text") == 0)) {	    if (infoPtr->flags & ASM_CODE) {		infoPtr->codeAddr = infoPtr->dot;	    } else {		infoPtr->dataAddr = infoPtr->dot;	    }	    if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) {		Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC);	    } else {		p = end;		infoPtr->codeAddr = i;	    }	    infoPtr->dot = infoPtr->codeAddr;	    infoPtr->flags |= ASM_CODE;	} else if ((pseudoOp[0] == 'w') && (strcmp(pseudoOp, "word") == 0)) {	    while (1) {		curToken = p;		if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end)			!= TCL_OK) {		    IndicateError(machPtr->interp, machPtr->interp->result,			    line, p);		    goto endOfLine;		}		infoPtr->dot = (infoPtr->dot + 3) & ~3;		(void) StoreWords(machPtr, infoPtr->dot, &i, 0, 1);		infoPtr->dot += 4;		for (p = end; (*p == ' ') || (*p == '\t'); p++) {		    /* Null body;  just skip space. */		}		if (*p != ',') {		    break;		}		p++;	    }	} else if ((pseudoOp[0] == 'f') && (strcmp(pseudoOp, "float") == 0)) {	    while (1) {		float f;		int *pi = (int *)&f;		curToken = p;		f = strtod(p, &end);		if (p == end) {		    IndicateError(machPtr->interp, "illegal floating number", line, p);		    goto endOfLine;		}		infoPtr->dot = (infoPtr->dot + 3) & ~3;		(void) StoreWords(machPtr, infoPtr->dot, pi, 0, 1);		infoPtr->dot += 4;		for (p = end; (*p == ' ') || (*p == '\t'); p++) {		    /* Null body;  just skip space. */		}		if (*p != ',') {		    break;		}		p++;	    }	} else if ((pseudoOp[0] == 'd') && (strcmp(pseudoOp, "double") == 0)) {	    while (1) {		double d;		int *pi = (int *)&d;		curToken = p;		d = strtod(p, &end);		if (p == end) {		    IndicateError(machPtr->interp, "illegal double number", line, p);		    goto endOfLine;		}		infoPtr->dot = (infoPtr->dot + 3) & ~3;		(void) StoreWords(machPtr, infoPtr->dot, pi, 0, 2);		infoPtr->dot += 8;		for (p = end; (*p == ' ') || (*p == '\t'); p++) {		    /* Null body;  just skip space. */		}		if (*p != ',') {		    break;		}		p++;	    }	} else {	    IndicateError(machPtr->interp, "unknown pseudo-op", line,		    curToken);	    goto endOfLine;	}	/*	 * Check for extraneous garbage at the end of the line.	 */	while (isspace(*p)) {	    p++;	}	if ((*p != '#') && (*p != 0)) {	    IndicateError(machPtr->interp, "extra junk at end of line",		    line, p);	}	/*	 * Done with the line.  If there has been an error, add it onto	 * the list of error messages that has accumulated during the	 * assembly.  Increase the storage allocated to error messages	 * if necessary to accommodate the new message.	 */	endOfLine:	if (*machPtr->interp->result != 0) {	    if (infoPtr->flags & ASM_SIZE_ONLY) {		Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC);	    } else {		AddErrMsg(machPtr->interp, infoPtr, 1);		if (infoPtr->errorCount > ASM_MAX_ERRORS) {		    goto endOfFile;		}	    }	}    }    endOfFile:    fclose(f);    if (infoPtr->flags & ASM_CODE) {	infoPtr->codeAddr = infoPtr->dot;    } else {	infoPtr->dataAddr = infoPtr->dot;    }}/* *---------------------------------------------------------------------- * * AddErrMsg -- * *	Given an error message in an interpreter, add it onto a list of *	error messages being accumulated for an assembly and clear the *	interpreter's message. * * Results: *	None. * * Side effects: *	The message is added to the list of messages in infoPtr, and *	the interpreter's result is re-initialized. * *---------------------------------------------------------------------- */static voidAddErrMsg(interp, infoPtr, addHeader)    Tcl_Interp *interp;			/* Interpreter containing error					 * message. */    register LoadInfo *infoPtr;		/* State of assembly, to which error					 * message is to be added. */    int addHeader;			/* Non-zero means tack on message					 * header identifying file and line					 * number. */{    int length, hdrLength, totalLength;    char header[100];    length = strlen(interp->result);    if (length == 0) {	return;    }    if (addHeader) {	sprintf(header, "%.50s(%d): ", infoPtr->file,		infoPtr->lineNum);    } else {	header[0] = 0;    }    hdrLength = strlen(header);    totalLength = hdrLength + length + 2;    /*     * Grow the error message area if the current area isn't large     * enough.     */    if (totalLength > ((infoPtr->message + infoPtr->totalBytes)	    - (infoPtr->end + 1))) {	char *newMsg;	if (infoPtr->totalBytes == 0) {	    infoPtr->totalBytes = 4*totalLength;	} else {	    infoPtr->totalBytes = 2*(infoPtr->totalBytes + totalLength);	}	newMsg = calloc(1, (unsigned) infoPtr->totalBytes);	if (infoPtr->message != NULL) {	    strcpy(newMsg, infoPtr->message);	    infoPtr->end += newMsg - infoPtr->message;	} else {	    infoPtr->end = newMsg;	}	infoPtr->message = newMsg;    }    if (infoPtr->end != infoPtr->message) {	*infoPtr->end = '\n';	infoPtr->end += 1;    }    sprintf(infoPtr->end, "%s%s", header, interp->result);    infoPtr->end += hdrLength + length;    infoPtr->errorCount += 1;    Tcl_Return(interp, (char *) NULL, TCL_STATIC);}/* *---------------------------------------------------------------------- * * StoreWords -- * *	Place a given range of words in the memory of a machine. * * Results: *	A standard Tcl result (normally TCL_OK plus empty string);  error *	information is returned through machPtr->interp. * * Side effects: *	MachPtr's memory is modified to hold new information. * *---------------------------------------------------------------------- */static intStoreWords(machPtr, address, wordPtr, codeLine, numWords)    register DLX *machPtr;		/* Machine into which to store. */    unsigned int address;		/* Word-aligned byte address in					 * machine's memory. */    int *wordPtr;			/* Words to store into machine's					 * memory. */    int codeLine;			/* Line in which the instruction is					   displayed in the .code.t window. */    int numWords;			/* Number of words to store. */{    int index;    register MemWord *memPtr;    for ( ; numWords > 0; wordPtr++, address += 4, numWords--) {	index = ADDR_TO_INDEX(address);	if (index >= machPtr->numWords) {	    sprintf(machPtr->interp->result,		    "can't store at address 0x%x:  no such memory location",		    address);	    return TCL_ERROR;	}	memPtr = machPtr->memPtr + index;	memPtr->value = *wordPtr;        memPtr->line = codeLine;	memPtr->opCode = OP_NOT_COMPILED;    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * IndicateError -- * *	Generate an error message that also points out the position *	in a string where the error was detected. * * Results: *	There is no return value.  Interp's result is modified to hold *	errMsg followed by string, with position pos highlighted in *	string. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidIndicateError(interp, errMsg, string, pos)    Tcl_Interp *interp;		/* Interpreter to hold error message.  The				 * result area must be in the initial				 * empty state. */    char *errMsg;		/* Message describing the problem. */    char *string;		/* Input string that contained the problem. */    char *pos;			/* Location in string of the character where				 * problem was detected. */{    int msgLength, stringLength;    char *newMsg;    msgLength = strlen(errMsg);    stringLength = strlen(string);    if (string[stringLength-1] == '\n') {	stringLength -= 1;    }    /*     * Always allocate new storage for the new message.  This is needed     * because (a) the space required may exceed the size of the static     * result buffer, and (b) "errMsg" may actually be in the static     * buffer so we have to be careful not to trash it while generating     * the new message.     */    newMsg = calloc(1, (unsigned) (msgLength + stringLength + 10));    sprintf(newMsg, "%s: %.*s => %.*s", errMsg, pos-string,	    string, stringLength - (pos-string), pos);    Tcl_Return(interp, newMsg, TCL_DYNAMIC);}

⌨️ 快捷键说明

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