string StringUtil::toHEX(int number) { return toHEX((unsigned int)number); }
string StringUtil::toHEX(long long number) { return toHEX((unsigned long long)number); }
int asmFile(std::string path, USHORT retMem[], int retSize, USHORT wAdd = 0, bool printLabel = false, labelList* retLblLst = NULL) { std::list<std::string>* err = preprocess(path); //处理部分预处理 if (err->empty() == false) throw(err); std::ifstream file("pp_temp"); std::list<std::string> fileName; std::list<int> lineCountLst; std::list<int>::iterator lineCount; fileName.push_back(path); lineCountLst.push_back(0); lineCount = lineCountLst.end(); lineCount--; if (!file.is_open()) throw(std::string("Can't Open File ") + path); char *line = new char[65536]; int *m = new int[0x200000]; bool *joined = new bool[0x200000]; memset(m, -1, sizeof(int) * 0x200000); memset(joined, false, sizeof(bool) * 0x200000); int retLen = 0; try { std::string insline; int markPos = std::string::npos; USHORT sysLblCount = 0; std::string sysLabel; labelList lblLst; pendList pendLst; std::string lbl; int pendCount = 0; labelList::iterator lblBeg, lblItr, lblEnd; std::list<labelList::iterator> lblUsedLst; std::list<labelList::iterator>::const_iterator usedItr, usedEnd; pendItem pendItm; std::string ppCmd, ppArg; defList defLst; defList::iterator defItr, defEnd; USHORT add = wAdd, addShift = wAdd; int len = 0, pendLen = 3, i; while (!file.eof()) { (*lineCount)++; file.getline(line, 65536, '\n'); insline = insline + line; trim(insline); if (insline.length() < 1) continue; markPos = insline.find(';'); if (markPos != std::string::npos) //注释 { if (markPos == 0) insline = ""; else { insline.erase(markPos - 1); trim(insline); } } markPos = insline.find(':'); //标签 if (markPos == 0) { markPos = insline.find(' '); if (markPos == std::string::npos) { lbl = insline.substr(1); insline = ""; } else { lbl = insline.substr(1, markPos - 1); insline.erase(0, markPos + 1); } if (lbl.find('$') != std::string::npos) { err->push_back(fileName.back() + ':' + toStr(*lineCount) + ":Illgeal label:" + lbl); } else { lblItr = lblLst.begin(); lblEnd = lblLst.end(); bool success = true; for (lblItr = lblLst.begin(); lblItr != lblEnd; lblItr++) { if (lblItr->str == lbl) { err->push_back(fileName.back() + ':' + toStr(*lineCount) + ":Duplicate label:" + lbl); success = false; } } if (success) lblLst.push_back(label(lbl, add, add)); } } if (insline.length() < 1) continue; if (insline.front() == '#') //预处理指令 { insline.erase(0, 1); markPos = insline.find(' '); if (markPos == std::string::npos) { ppCmd = insline; ppArg = ""; } else { ppCmd = insline.substr(0, markPos); ppArg = insline.substr(markPos + 1); } trim(ppCmd); lcase(ppCmd); trim(ppArg); if (ppCmd == "define") { markPos = ppArg.find(' '); if (markPos == std::string::npos) { ppCmd = ppArg; ppArg = ""; } else { ppCmd = ppArg.substr(0, markPos); ppArg = ppArg.substr(markPos + 1); } defItem newDefItm(ppCmd, ppArg); defEnd = defLst.end(); for (defItr = defLst.begin(); defItr != defEnd; defItr++) if ((*defItr) > newDefItm) break; defLst.insert(defItr, newDefItm); } else if (ppCmd == "undef") { defEnd = defLst.end(); for (defItr = defLst.begin(); defItr != defEnd; defItr++) if (defItr->name == ppArg) { defLst.erase(defItr); break; } } else if (ppCmd == "file") { fileName.push_back(ppArg); lineCountLst.push_back(0); lineCount = lineCountLst.end(); lineCount--; } else if (ppCmd == "/file") { fileName.pop_back(); lineCountLst.pop_back(); lineCount = lineCountLst.end(); if (!lineCountLst.empty()) lineCount--; } else { err->push_back(fileName.back() + ':' + toStr(*lineCount) + ":Undefined preprocess command"); } insline = ""; continue; } markPos = insline.find('$'); //类似于this的东西 if (markPos != std::string::npos) { sysLabel = "$__asm_sys_label_" + toHEX(sysLblCount); sysLblCount++; lblLst.push_back(label(sysLabel, add, add)); insline = insline.substr(0, markPos) + sysLabel + insline.substr(markPos + 1); } if (insline.length() < 1) continue; defEnd = defLst.end(); //替换宏定义 for (defItr = defLst.begin(); defItr != defEnd; defItr++) { markPos = insline.find(defItr->name); while (markPos != std::string::npos) { if ((markPos == 0 ? true : spacer[insline[markPos - 1]]) && (markPos == insline.length() - defItr->name.length() ? true : spacer[insline[markPos + defItr->name.length()]])) //防止#define a之类后dat之类被替换成dt insline = insline.substr(0, markPos) + defItr->val + insline.substr(markPos + defItr->name.length()); markPos = insline.find(defItr->name, min(markPos + 1, (int)(insline.length() - 1))); } } if (insline.back() == ',') continue; len = assembler(insline, arg_ret, 65536); switch (len) { case _ERR_ASM_NOT_SUPPORTED: err->push_back(fileName.back() + ':' + toStr(*lineCount) + ":Instruction " + line + " is not supported"); case _ERR_ASM_ILLEGAL: case _ERR_ASM_ILLEGAL_OP: err->push_back(fileName.back() + ':' + toStr(*lineCount) + ":Illegal instruction " + line); case _ERR_ASM_ILLEGAL_ARG: pendLst.push_back(pendItem(insline, add, 0x20, fileName.back(), *lineCount)); joined[add - addShift] = true; //为含有未能识别的标签的代码留出空间 add += 0x20; pendCount++; break; case _ERR_ASM_TOO_LONG: err->push_back("Instruction is too long"); default: for (i = 0; i < len; i++, add++) m[add - addShift] = arg_ret[i]; } insline = ""; } if (add > retSize) err->push_back("Instruction is too long"); if (err->empty() == false) throw(err); lblLst.sort(); //按标签长度从大到小排序以解决长标签与短标签内容部分重复时长标签被部分替换的问题 lblBeg = lblLst.begin(); lblEnd = lblLst.end(); int insLenAll = add; //处理未被识别的标签 while (!pendLst.empty()) { pendItm = pendLst.front(); pendLst.pop_front(); insline = pendItm.str; add = pendItm.pos; if (add < addShift) { err->push_back("Assembler Error"); throw(err); } joined[add - addShift] = false; pendLen = pendItm.len; for (i = 0; i < pendLen; i++) m[add + i - addShift] = -1; lblUsedLst.clear(); for (lblItr = lblBeg; lblItr != lblEnd; lblItr++) { markPos = insline.find(lblItr->str); bool used = false; while (markPos != std::string::npos) { if ((markPos == 0 ? true : spacer[insline[markPos - 1]]) && (markPos == insline.length() - lblItr->str.length() ? true : spacer[insline[markPos + lblItr->str.length()]])) //与处理宏定义时的超长判断用途一致 { used = true; insline = insline.substr(0, markPos) + "0x" + toHEX(lblItr->pos) + insline.substr(markPos + lblItr->str.length()); } markPos = insline.find(lblItr->str, min(markPos + 1, (int)(insline.length() - 1))); } if (used) lblUsedLst.push_back(lblItr); } len = assembler(insline, arg_ret, 65536); pendItm.len = len; usedEnd = lblUsedLst.cend(); //汇编完之后再将指令加入 标签被引用列表 以防止指令长度不对 for (usedItr = lblUsedLst.cbegin(); usedItr != usedEnd; usedItr++) { lblItr = *usedItr; pendList *usedList = &(lblItr->used); pendList::const_iterator itr, itrEnd = usedList->cend(); for (itr = usedList->cbegin(); itr != itrEnd; itr++) { if (itr->pos == add) { usedList->erase(itr); break; } } usedList->push_back(pendItm); } switch (len) { case _ERR_ASM_NOT_SUPPORTED: err->push_back(pendItm.file + ':' + toStr(pendItm.lineN) + ":Instruction " + pendItm.str + " is not supported"); case _ERR_ASM_ILLEGAL: case _ERR_ASM_ILLEGAL_OP: case _ERR_ASM_ILLEGAL_ARG: err->push_back(pendItm.file + ':' + toStr(pendItm.lineN) + ":Illegal instruction " + pendItm.str); case _ERR_ASM_TOO_LONG: err->push_back("Instruction is too long"); default: for (i = 0; i < len; i++, add++) m[add - addShift] = arg_ret[i]; //由于指令实际长度比预留空间短,在该指令后面的标签需要往前凑 if (len < pendLen) { pendLen = pendLen - len; for (lblItr = lblBeg; lblItr != lblEnd; lblItr++) { if (lblItr->originPos > add) { lblItr->pos -= pendLen; //将含有被修改地址的标签的指令重新加入处理队列以用新值替换旧值 pendList *usedList = &(lblItr->used); pendList::const_iterator itr, itrEnd = usedList->cend(); for (itr = usedList->cbegin(); itr != itrEnd; itr++) { if (!joined[itr->pos]) { pendLst.push_back(*itr); joined[itr->pos] = true; } } } } } } } if (err->empty() == false) throw(err); if (printLabel && retLblLst != NULL) { retLblLst->clear(); for (lblItr = lblBeg; lblItr != lblEnd; lblItr++) retLblLst->push_back(label(lblItr->str, lblItr->pos, 0)); } add = wAdd; int emptyCount = 0; for (i = 0; add < insLenAll && i < 0x200000; i++) { if (m[i] < 0) { continue; emptyCount++; } retLen++; retMem[add++] = m[i]; } } catch (std::list<std::string>* err) { file.close(); delete[] line; delete[] m; throw(err); } catch (std::string err) { file.close(); delete[] line; delete[] m; throw(err); } file.close(); delete[] line; delete[] m; return retLen; }