日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实现一个汇编器

發布時間:2025/6/15 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现一个汇编器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? 上文《匯編器源碼剖析》中,我們對一匯編器進行了源碼剖析,這里我們仿照其實現一個自己版本的匯編器,90%的東西都是借鑒于上文中的源碼。

???????? 實現一個匯編器,首先需要定義一個匯編指令集,這里我們還是沿用上文中的匯編指令集。匯編指令與指令之間是一一對應的關系,也就是說是直譯的過程。我們的指令集是枚舉類型,也是沿用上文源碼的指令集。

???????? 我們的函數功能是對輸入的匯編指令,將其讀入,翻譯成對應的二進制代碼,然后將其輸出。

???????? 實現匯編器的重點在于理解匯編器的原理,而匯編器的原理就在于定義好匯編指令集、二進制指令集,并且確定好二者之間的映射轉換關系。

? ? ? ? ?以上即是匯編器的原理。具體如何定義匯編指令集、二進制指令集,如何實現匯編到二進制的映射轉換,是具體的實現細節,不同的應用場景實現方法可能不同。

???????? 這里,我們給出最為簡單的一種實現模型,我們先給出代碼,然后根據代碼講解具體的實現細節。

// 實現一個簡單的匯編器 #include <iostream> #include <sstream> #include <string> #include <vector> #include <map> using namespace std;enum BinIns;// 二進制指令結構體 // 指令碼+操作數 struct Instruction {BinIns op; // 指令碼只占一個字節int arg; // 操作數,占四個字節 };// 枚舉類型的二進制指令集 enum BinIns {binHalt, binIn, binOut, binAdd, binSub, binMul, binDiv,binDup,binLd, binSt, binLdc, binJlt, binJle, binJgt, binJge, binJeq, binJne, binJmp,binInvalid };// 初始化匯編指令集 void InitAssembleInstructions(vector<string>& assIns) {assIns.clear();assIns.push_back("HALT");assIns.push_back("IN");assIns.push_back("OUT");assIns.push_back("ADD");assIns.push_back("SUB");assIns.push_back("MUL");assIns.push_back("DIV");assIns.push_back("DUP");assIns.push_back("LD");assIns.push_back("ST");assIns.push_back("LDC");assIns.push_back("JLT");assIns.push_back("JLE");assIns.push_back("JGT");assIns.push_back("JGE");assIns.push_back("JEQ");assIns.push_back("JNE");assIns.push_back("JMP"); }// 初始化 // 指令-參數個數 void InitInstrctionArgNumber(map<BinIns, int>& insArgNum) {insArgNum.clear();insArgNum[binHalt] = 0;insArgNum[binIn] = 0;insArgNum[binOut] = 0;insArgNum[binAdd] = 0;insArgNum[binSub] = 0;insArgNum[binMul] = 0;insArgNum[binDiv] = 0;insArgNum[binDup] = 0;insArgNum[binLd] = 0;insArgNum[binSt] = 0;insArgNum[binLdc] = 1;insArgNum[binJlt] = 1;insArgNum[binJle] = 1;insArgNum[binJgt] = 1;insArgNum[binJge] = 1;insArgNum[binJeq] = 1;insArgNum[binJne] = 1;insArgNum[binJmp] = 1;insArgNum[binInvalid] = 1; }// 建立匯編指令到二進制指令的映射 // 初始化 void InitAssembleToBinary(const vector<string>& assIns, map<string, BinIns>& assToBin) {assToBin.clear();for (auto i = 0; i != assIns.size(); ++i){// assIns和BinIns的指令次序一致assToBin[assIns[i]] = static_cast<BinIns>(i);} }// 讀入匯編指令 void ReadAssemble(vector<string>& ass) {ass.clear();string line;while (getline(cin, line)){ass.push_back(line);} }// 顯示 void Display(const vector<string>& bar) {for (auto i = 0; i != bar.size(); ++i){cout << bar[i] << endl;} }string StringToUpper(const string& str) {string ret;for (auto i = 0; i != str.size(); ++i){ret += toupper(str[i]);}return ret; }void AssembleToBinary(const vector<string>& ass,vector<Instruction>& bin,const map<string, BinIns>& assToBin,map<BinIns, int>& insArgNum) {string assline;// 將ass匯總for (auto i = 0; i != ass.size(); ++i){assline += StringToUpper(ass[i]) + '\t';}cout << assline << endl;istringstream sin(assline);string strOp, strArg;Instruction ins;BinIns op;int arg;while (sin >> strOp){auto cit = assToBin.find(strOp);if (cit == assToBin.end()){// 沒有找到對應的指令碼// 忽略處理 ;break;}op = cit->second;// insArgNum為非const型// assToBin const型保障了insArgNum[]不會存在更新的情況int argNum = insArgNum[op];if (argNum > 0){sin >> strArg;arg = atoi(strArg.c_str());}else{arg = 0;}ins.op = op;ins.arg = arg;bin.push_back(ins);} }string IntToString(int n, int sizeofbytes) {string ret;ret.resize(sizeofbytes * 8, '0');for (int i = ret.size() - 1; i >= 0 && n != 0; --i, n /= 2){ret[i] = n % 2 + '0';}return ret; }void OutputBinary(const vector<Instruction>& bin,const map<BinIns, int>& insArgNum) {for (auto i = 0; i != bin.size(); ++i){cout << bin[i].op;cout << '\t' << IntToString(bin[i].op, 1);auto cit = insArgNum.find(bin[i].op);if (cit == insArgNum.end()){// 如果沒有找到// 不做處理 ;break;}if (cit->second > 0){cout << '\t' << bin[i].arg;cout << '\t' << IntToString(bin[i].arg, 4);}cout << endl;} }int main() {// 匯編指令集vector<string> assIns;InitAssembleInstructions(assIns);// 二進制指令-操作數個數map<BinIns, int> insArgNum;InitInstrctionArgNumber(insArgNum);// 匯編指令到二進制的映射map<string, BinIns> assToBin;InitAssembleToBinary(assIns, assToBin);vector<string> ass; // 保持讀入的匯編指令 ReadAssemble(ass);cout << endl;Display(ass);cout << endl;vector<Instruction> bin; // 保存二進制指令 AssembleToBinary(ass, bin, assToBin, insArgNum);OutputBinary(bin, insArgNum);cout << endl;return 0; }

測試樣例

?

???????? 下面我們對程序進行如下解釋。

?????????數據結構

???????? Instruction:指令結構體,有兩個元素op和arg,分別對應于指令碼和操作數。op最多需要一個操作數。

???????? BinIns:枚舉類型,二進制指令集。

???????? AssIns:vector<string>類型,匯編指令集

???????? insArgNum:map<BinIns, int>類型,用來記錄二進制指令對應的操作數個數

???????? assToBin:map<string, BinIns>類型,匯編指令到二進制指令的映射,用于匯編指令到二進制指令的轉換操作

???????? ass:vector<string>類型,用于存儲輸入的匯編指令

???????? bin:vector<Instruction>類型,用于存儲由匯編指令轉換的二進制指令

?????????操作函數

???????? InitAssembleInstruction:用于初始化匯編指令集

???????? InitInstructionArgNumber:用于初始化二進制指令對應的操作數個數

???????? InitAssembleToBinary:用于初始化匯編指令到二進制指令的映射

???????? ReadAssemble:用于讀入匯編指令

???????? Display:用于顯示讀入的匯編指令

???????? AssembleToBinary:用于將匯編指令轉換為二進制指令

???????? OutputBinary:用于將轉換后的二進制指令輸出

???????? StringToUpper:用于將匯編代碼統一轉換為大寫,這樣可以忽略匯編代碼的大小寫

???????? IntToString:用于將int型數轉換為二進制形式

???????? main:測試函數,先將assIns、insArgNum、assToBin等初始化,讀入匯編指令,并將其轉換二進制指令,最后將轉換后的二進制指令輸出。

?

???????? 匯編器實現的關鍵三點:匯編指令的表示、二進制指令的表示、匯編指令到二進制指令之間的轉換三個方面。

???????? 在程序中我們對輸入的匯編指令是按照空白符間隔的方式進行的匯編代碼切分,如果進一步改進,可以對匯編代碼進行詞法分析,切分出匯編token——指令碼和操作數,然后將指令碼和操作數翻譯成對應的二進制代碼。

???????? 接下來,我們會分析一個反匯編器的源代碼,然后根據反匯編器的實現原理,實現一個自己的反匯編器。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的实现一个汇编器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。