├── .gitignore ├── Assembler ├── Assembler.sln ├── Common.h ├── Elf_File.cpp ├── Elf_File.h ├── Generate.cpp ├── Generate.h ├── Lexer.cpp ├── Lexer.h ├── Makefile ├── Parser.cpp ├── Parser.h ├── Semantic.cpp ├── Semantic.h ├── ass_test │ ├── common.s │ ├── common.s.t │ ├── test.s │ └── test.s.t ├── elf.h ├── main.cpp └── make.bat ├── Compiler ├── Common.h ├── Compiler.sln ├── Generator.cpp ├── Generator.h ├── Lexer.cpp ├── Lexer.h ├── Makefile ├── Parser.cpp ├── Parser.h ├── Semantic.cpp ├── Semantic.h ├── common.s ├── compiler_test │ ├── test.s │ ├── test.tc │ ├── test1.s │ ├── test1.tc │ ├── test2.tc │ ├── test3.tc │ ├── test4.tc │ ├── test5.tc │ ├── test6.tc │ ├── test7.tc │ ├── test8.s │ ├── test8.tc │ ├── test9.s │ └── test9.tc ├── main.cpp └── make.bat ├── Linker ├── Common.h ├── Elf_File.cpp ├── Elf_File.h ├── Link.cpp ├── Link.h ├── Linker.sln ├── Makefile ├── elf.h ├── main.cpp └── make.bat ├── Makefile ├── README.md ├── document ├── JCC-document.pdf ├── README.md └── src │ ├── CFG-design.drawio │ ├── CFG.drawio │ ├── DFA.drawio │ ├── FA-demo.drawio │ ├── FA.drawio │ ├── FIRST.drawio │ ├── LSMP.drawio │ ├── NFA.drawio │ ├── RE-NFA-demo.drawio │ ├── RE-NFA.drawio │ ├── Right-Linear-G.drawio │ ├── as-递归下降.drawio │ ├── demo.png │ ├── demo1.png │ ├── demo2.png │ ├── epsilon-question.drawio │ ├── for_loop.drawio │ ├── 指令.drawio │ ├── 注释识别.drawio │ └── 递归下降.drawio ├── main.cpp ├── make.bat ├── make_tool ├── README.md └── make.exe ├── run.bat └── test ├── common.s ├── common.s.t ├── test.s ├── test.s.t └── test.tc /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # other 35 | Compiler/.vs/ 36 | Compiler/Debug/ 37 | Assembler/Debug/ 38 | Linker/Debug/ 39 | .vs/ 40 | *.user 41 | *.vcxproj 42 | *.filters 43 | *. 44 | # exclusive 45 | !make.exe 46 | !make.bat 47 | -------------------------------------------------------------------------------- /Assembler/Assembler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Assembler", "Assembler.vcxproj", "{3FA39E99-6BBD-4710-96D4-EE26198B6036}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Debug|x64.ActiveCfg = Debug|x64 17 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Debug|x64.Build.0 = Debug|x64 18 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Debug|x86.ActiveCfg = Debug|Win32 19 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Debug|x86.Build.0 = Debug|Win32 20 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Release|x64.ActiveCfg = Release|x64 21 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Release|x64.Build.0 = Release|x64 22 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Release|x86.ActiveCfg = Release|Win32 23 | {3FA39E99-6BBD-4710-96D4-EE26198B6036}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {381DE5A8-1768-4847-99BF-AE98CBAE1AFD} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Assembler/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | #define MAX_LEN 80 7 | #define ID_LEN 30 8 | #define STRING_LEN 255 9 | #define RESERVED_NUMBER 48 10 | #define NUM_LENGTH 9 11 | 12 | #define al "al" 13 | #define cl "cl" 14 | #define dl "dl" 15 | #define bl "bl" 16 | 17 | #define ah "ah" 18 | #define ch "ch" 19 | #define dh "dh" 20 | #define bh "bh" 21 | 22 | #define eax "eax" 23 | #define ecx "ecx" 24 | #define edx "edx" 25 | #define ebx "ebx" 26 | 27 | #define esp "esp" 28 | #define ebp "ebp" 29 | #define esi "esi" 30 | #define edi "edi" 31 | 32 | #define mov "mov" 33 | #define cmp "cmp" 34 | #define sub "sub" 35 | #define add "add" 36 | #define lea "lea" 37 | #define call "call" 38 | #define sys_int "int" 39 | #define imul "imul" 40 | #define idiv "idiv" 41 | #define neg "neg" 42 | #define inc "inc" 43 | #define dec "dec" 44 | #define jmp "jmp" 45 | #define je "je" 46 | #define jg "jg" 47 | #define jl "jl" 48 | #define jge "jge" 49 | #define jle "jle" 50 | #define jne "jne" 51 | #define jna "jna" 52 | #define _push "push" 53 | #define _pop "pop" 54 | #define _ret "ret" 55 | #define _section "section" 56 | #define global "global" 57 | #define equ "equ" 58 | #define times "times" 59 | #define db "db" 60 | #define dw "dw" 61 | #define dd "dd" 62 | #define land "and" 63 | #define lor "or" 64 | 65 | 66 | #define IMMD 1 67 | #define REGS 2 68 | #define MEMO 3 69 | 70 | 71 | #define LAB_HEAD "@lab_" 72 | #define IF_HEAD "@if_" 73 | #define WHILE_HEAD "@while_" 74 | #define FOR_HEAD "@for_" 75 | #define CAL_HEAD "@cal_" 76 | #define STACK_HEAD "@s_stack" 77 | 78 | #define TEXT_SEG ".text" 79 | #define DATA_SEG ".data" 80 | #define REL_TEXT_SEG ".rel.text" 81 | #define REL_DATA_SEG ".rel.data" 82 | #define BSS_SEG ".bss" 83 | #define SH_STR_SEG ".shstrtab" 84 | #define SYM_SEG ".symtab" 85 | #define STR_SEG ".strtab" 86 | 87 | #define STR2LONG "@str2long" 88 | #define PROC_BUF "@procBuf" 89 | 90 | 91 | enum symbol { 92 | null, ident, excep, number, strings, 93 | addi, subs, comma, lbrac, 94 | rbrac, colon, 95 | rev_al, rev_cl, rev_dl, rev_bl, 96 | rev_ah, rev_ch, rev_dh, rev_bh, 97 | rev_eax, rev_ecx, rev_edx, rev_ebx, 98 | rev_esp, rev_ebp, rev_esi, rev_edi, 99 | rev_mov, rev_cmp, rev_sub, rev_add, rev_lea,rev_and,rev_or, 100 | rev_call, rev_sys_int, rev_imul, rev_idiv, 101 | rev_neg, rev_inc, rev_dec, rev_jmp, 102 | rev_je, rev_jg, rev_jl, rev_jge, 103 | rev_jle, rev_jne, rev_jna, rev_push, 104 | rev_pop, rev_ret, rev_section, rev_global, 105 | rev_equ, rev_times, rev_db, rev_dw, rev_dd 106 | }; 107 | 108 | enum error_c { 109 | // lexer error 110 | line2long, id2long, num2long, str2long, excep_sym, string_wrong, 111 | // syntax error 112 | ident_lost, times_wrong, equ_wrong, len_type_wrong, 113 | type_wrong, comma_lost, instruction_wrong, subs_non_number, 114 | regs_wrong, rbrac_lost, lbrac_lost, immd_non_des, MEMO_non_both, 115 | }; 116 | 117 | 118 | // 119 | // aux routines for colorful printf. And you should not pay more attention to them 120 | // 121 | #define xINFO(_X_,...) color_printf(FG_WHITE,_X_,__VA_ARGS__) 122 | 123 | #define xPANIC(_X_,...) color_printf(FG_RED,_X_,__VA_ARGS__) 124 | 125 | #define xSUCC(_X_,...) color_printf(FG_GREEN,_X_,__VA_ARGS__) 126 | 127 | #define xWARN(_X_,...) color_printf(FG_YELLOW,_X_,__VA_ARGS__) 128 | 129 | 130 | #define FG_BLACK 0x00 131 | #define FG_BLUE 0x01 132 | #define FG_GREEN 0x02 133 | #define FG_BLUE_2 0x03 134 | #define FG_RED 0x04 135 | #define FG_PURPLE 0x05 136 | #define FG_YELLOW 0x06 137 | #define FG_WHITE 0x0F 138 | 139 | inline void setColor(int color, const bool bIntensity = true) { 140 | SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color | (bIntensity ? FOREGROUND_INTENSITY : 0)); 141 | } 142 | 143 | inline void resetColor() { 144 | setColor(FG_WHITE); 145 | } 146 | 147 | inline int color_printf(const int color, const char* pszFmt, ...) { 148 | if (color != -1) { 149 | setColor(color); 150 | } 151 | va_list marker; 152 | va_start(marker, pszFmt); 153 | auto ri = vprintf(pszFmt, marker); 154 | va_end(marker); 155 | resetColor(); 156 | return ri; 157 | } -------------------------------------------------------------------------------- /Assembler/Elf_File.cpp: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | #include "Elf_File.h" 3 | #include "Common.h" 4 | 5 | 6 | Reloc::Reloc() { 7 | this->name = ""; 8 | this->offset = 0; 9 | this->target_seg = ""; 10 | this->type = 0; 11 | } 12 | 13 | Reloc::Reloc(string seg, int addr, string name, int type) { 14 | this->target_seg = seg; 15 | this->offset = addr; 16 | this->name = name; 17 | this->type = type; 18 | } 19 | 20 | string Reloc::get_target_seg() { 21 | return target_seg; 22 | } 23 | 24 | int Reloc::get_offset() { 25 | return offset; 26 | } 27 | 28 | string Reloc::get_name() { 29 | return name; 30 | } 31 | 32 | int Reloc::get_type() { 33 | return type; 34 | } 35 | 36 | void Reloc::set_target_seg(string seg) { 37 | this->target_seg = seg; 38 | } 39 | 40 | void Reloc::set_offset(int offset) { 41 | this->offset = offset; 42 | } 43 | 44 | void Reloc::set_name(string name) { 45 | this->name = name; 46 | } 47 | 48 | void Reloc::set_type(int type) { 49 | this->type = type; 50 | } 51 | 52 | Elf32_Ehdr Elf_File::ehdr; 53 | unordered_mapElf_File::shdr_tab; 54 | vectorElf_File::shdr_name; 55 | unordered_mapElf_File::sym_tab; 56 | vectorElf_File::sym_name; 57 | vectorElf_File::rel_tab; 58 | 59 | char* Elf_File::sh_str_tab = nullptr; 60 | int Elf_File::shstrtab_size = 0; 61 | char* Elf_File::str_tab = nullptr; 62 | int Elf_File::strtab_size = 0; 63 | vectorElf_File::rel_text_tab; 64 | vectorElf_File::rel_data_tab; 65 | FILE* Elf_File::fin = nullptr; 66 | 67 | 68 | void Elf_File::Init() { 69 | sh_str_tab = nullptr; 70 | str_tab = nullptr; 71 | fin = nullptr; 72 | shstrtab_size = 0; 73 | strtab_size = 0; 74 | shdr_tab.clear(); 75 | shdr_name.clear(); 76 | rel_tab.clear(); 77 | sym_name.clear(); 78 | rel_data_tab.clear(); 79 | rel_text_tab.clear(); 80 | sym_tab.clear(); 81 | 82 | AddShdr("", 0, 0, 0, 0, 0, 0, 0, 0, 0); 83 | AddSym("", nullptr); 84 | } 85 | 86 | int Elf_File::GetSegIndex(string name) { 87 | int index = 0; 88 | for (int i = 0; i < shdr_name.size(); i++) { 89 | if (shdr_name[i] == name) { 90 | break; 91 | } 92 | index++; 93 | } 94 | return index; 95 | } 96 | 97 | int Elf_File::GetSymIndex(string name) { 98 | int index = 0; 99 | for (int i = 0; i < sym_name.size(); i++) { 100 | if (sym_name[i] == name) { 101 | break; 102 | } 103 | index++; 104 | } 105 | return index; 106 | } 107 | 108 | void Elf_File::AddShdr(string name, int size,int data_length) { 109 | int offset = 52 + data_length; 110 | if (name == ".text") { 111 | AddShdr(name, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0, offset, size, 0, 0, 4, 0); 112 | } 113 | else if (name == ".data") { 114 | AddShdr(name, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE, 0, offset, size, 0, 0, 4, 0); 115 | } 116 | else if (name == ".bss") { 117 | AddShdr(name, SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 0, offset, size, 0, 0, 4, 0); 118 | } 119 | return; 120 | } 121 | 122 | void Elf_File::AddShdr(string sh_name, Elf32_Word sh_type, Elf32_Word sh_flag, 123 | Elf32_Addr sh_addr, Elf32_Off sh_offset, Elf32_Word sh_size, 124 | Elf32_Word sh_link, Elf32_Word sh_info, Elf32_Word sh_addr_align, 125 | Elf32_Word sh_enter_size) { 126 | Elf32_Shdr* sh = new Elf32_Shdr(); 127 | sh->sh_name = 0; 128 | sh->sh_type = sh_type; 129 | sh->sh_flags = sh_flag; 130 | sh->sh_addr = sh_addr; 131 | sh->sh_offset = sh_offset; 132 | sh->sh_size = sh_size; 133 | sh->sh_link = sh_link; 134 | sh->sh_info = sh_info; 135 | sh->sh_addralign = sh_addr_align; 136 | sh->sh_entsize = sh_enter_size; 137 | shdr_tab[sh_name] = sh; 138 | shdr_name.push_back(sh_name); 139 | } 140 | 141 | 142 | void Elf_File::AddSym(string name, Elf32_Sym* s) { 143 | sym_tab[name] = new Elf32_Sym(); 144 | Elf32_Sym* sym = sym_tab[name]; 145 | if (name == "") { 146 | sym->st_name = 0; 147 | sym->st_value = 0; 148 | sym->st_size = 0; 149 | sym->st_info = 0; 150 | sym->st_other = 0; 151 | sym->st_shndx = 0; 152 | } 153 | else { 154 | sym->st_name = 0; 155 | sym->st_value = s->st_value; 156 | sym->st_size = s->st_size; 157 | sym->st_info = s->st_info; 158 | sym->st_other = s->st_other; 159 | sym->st_shndx = s->st_shndx; 160 | } 161 | sym_name.push_back(name); 162 | } 163 | 164 | void Elf_File::AddSym(VarRecord* var) { 165 | bool is_global = false; 166 | string name = var->get_sym_name(); 167 | if (name.find(LAB_HEAD) == 0 || name.find(IF_HEAD) == 0 || 168 | name.find(WHILE_HEAD) == 0 || name.find(FOR_HEAD) == 0 || 169 | name.find(CAL_HEAD) == 0 || name.find(STACK_HEAD) == 0) { 170 | return; 171 | } 172 | if (var->get_seg_name() == TEXT_SEG) { 173 | if (name == STR2LONG || name == PROC_BUF) { 174 | is_global = true; 175 | } 176 | else if (name[0] != '@') { 177 | is_global = true; 178 | } 179 | } 180 | else if (var->get_seg_name() == DATA_SEG) { 181 | int index = name.find("@str_"); 182 | if (index == 0 && name.size() >= 5) { 183 | is_global = !(name[5] >= '0' && name[5] <= '9'); 184 | } 185 | else { 186 | is_global = true; 187 | } 188 | } 189 | else if (var->get_seg_name() == "") { 190 | is_global = var->get_is_externed(); 191 | } 192 | 193 | Elf32_Sym* sym = new Elf32_Sym(); 194 | sym->st_name = 0; 195 | sym->st_value = var->get_addr(); 196 | sym->st_size = var->get_times() * var->get_len_type() * var->get_sym_length(); 197 | if (is_global) 198 | sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE); 199 | else 200 | sym->st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE); 201 | sym->st_other = 0; 202 | if (var->get_is_externed()) 203 | sym->st_shndx = STN_UNDEF; 204 | else 205 | sym->st_shndx = GetSegIndex(var->get_seg_name()); 206 | AddSym(var->get_sym_name(), sym); 207 | return; 208 | } 209 | 210 | Reloc* Elf_File::AddReloc(string seg, int addr, string name, int type) { 211 | Reloc* rel = new Reloc(seg, addr, name, type); 212 | rel_tab.push_back(rel); 213 | return rel; 214 | } 215 | 216 | void Elf_File::PaddingSeg(string prev, string next) { 217 | char padding = 0; 218 | int padding_number = shdr_tab[next]->sh_offset - 219 | (shdr_tab[prev]->sh_offset + shdr_tab[prev]->sh_size); 220 | while (padding_number--) { 221 | Generate::WriteBytes(padding, 1); 222 | } 223 | } 224 | 225 | void Elf_File::AssembleObj(int data_length) { 226 | int* pointer = (int*)ehdr.e_ident; 227 | *pointer = 0x464c457f; 228 | pointer++; 229 | *pointer = 0x00010101; 230 | pointer++; 231 | *pointer = 0x00; 232 | pointer++; 233 | *pointer = 0x00; 234 | ehdr.e_type = ET_REL; 235 | ehdr.e_machine = EM_386; 236 | ehdr.e_version = EV_CURRENT; 237 | ehdr.e_entry = 0; 238 | ehdr.e_phoff = 0; 239 | ehdr.e_flags = 0; 240 | ehdr.e_ehsize = 52; 241 | ehdr.e_phentsize = 0; 242 | ehdr.e_phnum = 0; 243 | ehdr.e_shentsize = 40; 244 | ehdr.e_shnum = 9; 245 | ehdr.e_shstrndx = 4; 246 | // 247 | int cur_offset = 52 + data_length; 248 | shstrtab_size = 51; 249 | /* (string(REL_TEXT_SEG) + REL_DATA_SEG + BSS_SEG 250 | + SH_STR_SEG + SYM_SEG + STR_SEG).size + 5; */ 251 | sh_str_tab = new char[shstrtab_size]; 252 | char* str = sh_str_tab; 253 | int index = 0; 254 | unordered_mapshstr_index; 255 | 256 | shstr_index[REL_TEXT_SEG] = index; 257 | strcpy(str + index, REL_TEXT_SEG); 258 | 259 | shstr_index[TEXT_SEG] = index + 4; 260 | index += 10; 261 | shstr_index[""] = index - 1; 262 | 263 | shstr_index[REL_DATA_SEG] = index; 264 | strcpy(str + index, REL_DATA_SEG); 265 | 266 | shstr_index[DATA_SEG] = index + 4; 267 | index += 10; 268 | 269 | shstr_index[BSS_SEG] = index; 270 | strcpy(str + index, BSS_SEG); 271 | index += 5; 272 | 273 | shstr_index[SH_STR_SEG] = index; 274 | strcpy(str + index, SH_STR_SEG); 275 | index += 10; 276 | 277 | shstr_index[SYM_SEG] = index; 278 | strcpy(str + index, SYM_SEG); 279 | index += 8; 280 | 281 | shstr_index[STR_SEG] = index; 282 | strcpy(str + index, STR_SEG); 283 | index += 8; 284 | 285 | AddShdr(SH_STR_SEG, /* string sh_name */ 286 | SHT_STRTAB, /* Elf32_Word sh_type */ 287 | 0, /* Elf32_Word sh_flag */ 288 | 0, /* Elf32_Addr sh_addr */ 289 | cur_offset, /* Elf32_Off sh_offset */ 290 | shstrtab_size, /* Elf32_Word sh_size */ 291 | SHN_UNDEF, /* Elf32_Word sh_link */ 292 | 0, /* Elf32_Word sh_info */ 293 | 1, /* Elf32_Word sh_addr_align */ 294 | 0); /* Elf32_Word sh_enter_size */ 295 | cur_offset += shstrtab_size; 296 | ehdr.e_shoff = cur_offset; 297 | cur_offset += 9 * 40; 298 | AddShdr(SYM_SEG, SHT_SYMTAB, 0, 0, cur_offset, sym_name.size() * 16, 0, 0, 1, 16); 299 | shdr_tab[SYM_SEG]->sh_link = GetSegIndex(SYM_SEG) + 1; 300 | strtab_size = 0; 301 | for (int i = 0; i < sym_name.size(); i++) { 302 | strtab_size += sym_name[i].size() + 1; 303 | } 304 | cur_offset += sym_name.size() * 16; 305 | AddShdr(STR_SEG, SHT_STRTAB, 0, 0, cur_offset, strtab_size, SHN_UNDEF, 0, 1, 0); 306 | str_tab = new char[strtab_size]; 307 | str = str_tab; 308 | index = 0; 309 | for (int i = 0; i < sym_name.size(); i++) { 310 | sym_tab[sym_name[i]]->st_name = index; 311 | strcpy(str + index, sym_name[i].c_str()); 312 | index += (sym_name[i].size() + 1); 313 | } 314 | 315 | // rel 316 | for (int i = 0; i < rel_tab.size(); i++) { 317 | Elf32_Rel* rel = new Elf32_Rel(); 318 | rel->r_offset = rel_tab[i]->get_offset(); 319 | rel->r_info = ELF32_R_INFO((Elf32_Word)GetSymIndex(rel_tab[i]->get_name()), rel_tab[i]->get_type()); 320 | if (rel_tab[i]->get_target_seg() == TEXT_SEG) { 321 | rel_text_tab.push_back(rel); 322 | } 323 | else if (rel_tab[i]->get_target_seg() == DATA_SEG) { 324 | rel_data_tab.push_back(rel); 325 | } 326 | } 327 | cur_offset += strtab_size; 328 | AddShdr(REL_TEXT_SEG, SHT_REL, 0, 0, cur_offset, rel_text_tab.size() * 8, GetSegIndex(SYM_SEG), GetSegIndex(TEXT_SEG), 1, 8); 329 | 330 | cur_offset += rel_text_tab.size() * 8; 331 | AddShdr(REL_DATA_SEG, SHT_REL, 0, 0, cur_offset, rel_data_tab.size() * 8, GetSegIndex(SYM_SEG), GetSegIndex(DATA_SEG), 1, 8); 332 | 333 | for (int i = 0; i < shdr_name.size(); i++) { 334 | int index = shstr_index[shdr_name[i]]; 335 | shdr_tab[shdr_name[i]]->sh_name = index; 336 | } 337 | } 338 | 339 | void Elf_File::WriteElfTail() { 340 | Generate::WriteBytes(sh_str_tab, shstrtab_size); 341 | 342 | for (int i = 0; i < shdr_name.size(); i++) { 343 | Elf32_Shdr* sh = shdr_tab[shdr_name[i]]; 344 | Generate::WriteBytes(sh, ehdr.e_shentsize); 345 | } 346 | 347 | for (int i = 0; i < sym_name.size(); i++) { 348 | Elf32_Sym* sym = sym_tab[sym_name[i]]; 349 | Generate::WriteBytes(sym, sizeof(Elf32_Sym)); 350 | } 351 | 352 | Generate::WriteBytes(str_tab, strtab_size); 353 | 354 | for (int i = 0; i < rel_text_tab.size(); i++) { 355 | Elf32_Rel* rel = rel_text_tab[i]; 356 | Generate::WriteBytes(rel, sizeof(Elf32_Rel)); 357 | } 358 | 359 | for (int i = 0; i < rel_data_tab.size(); i++) { 360 | Elf32_Rel* rel = rel_data_tab[i]; 361 | Generate::WriteBytes(rel, sizeof(Elf32_Rel)); 362 | } 363 | } 364 | 365 | void Elf_File::WriteElf(string name,int data_length,bool scan) { 366 | Generate::Over(); 367 | Generate::Init(name + ".o"); 368 | AssembleObj(data_length); 369 | Generate::WriteBytes(&ehdr, ehdr.e_ehsize); 370 | fin = fopen((name + ".t").c_str(), "rb"); 371 | char buffer[1024] = { 0 }; 372 | int read_length = -1; 373 | while (read_length != 0) { 374 | read_length = fread(buffer, 1, 1024, fin); 375 | Generate::WriteBytes(&buffer, read_length); 376 | } 377 | PaddingSeg(TEXT_SEG, DATA_SEG); 378 | Table::Write(scan); 379 | PaddingSeg(DATA_SEG, BSS_SEG); 380 | WriteElfTail(); 381 | } 382 | 383 | void Elf_File::Over() { 384 | unordered_map::iterator vi, vend; 385 | vend = shdr_tab.end(); 386 | for (vi = shdr_tab.begin(); vi != vend; vi++) { 387 | delete vi->second; 388 | } 389 | shdr_tab.clear(); 390 | 391 | shdr_name.clear(); 392 | shdr_name.shrink_to_fit(); 393 | 394 | unordered_map < string, Elf32_Sym* > ::iterator si, send; 395 | send = sym_tab.end(); 396 | for (si = sym_tab.begin(); si != send; si++) { 397 | delete si->second; 398 | } 399 | sym_tab.clear(); 400 | 401 | for (int i = 0; i < rel_tab.size(); i++) { 402 | delete rel_tab[i]; 403 | } 404 | rel_tab.clear(); 405 | rel_tab.shrink_to_fit(); 406 | 407 | for (int i = 0; i < rel_data_tab.size(); i++) { 408 | delete rel_data_tab[i]; 409 | } 410 | rel_data_tab.clear(); 411 | rel_data_tab.shrink_to_fit(); 412 | 413 | for (int i = 0; i < rel_text_tab.size(); i++) { 414 | delete rel_text_tab[i]; 415 | } 416 | rel_text_tab.clear(); 417 | rel_text_tab.shrink_to_fit(); 418 | } -------------------------------------------------------------------------------- /Assembler/Elf_File.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Semantic.h" 7 | #include "Generate.h" 8 | #include "elf.h" 9 | 10 | class VarRecord; 11 | 12 | 13 | using namespace std; 14 | 15 | class Reloc { 16 | private: 17 | string target_seg; 18 | int offset; 19 | string name; 20 | int type; 21 | public: 22 | Reloc(); 23 | Reloc(string seg, int addr, string name, int type); 24 | 25 | string get_target_seg(); 26 | int get_offset(); 27 | string get_name(); 28 | int get_type(); 29 | 30 | void set_target_seg(string seg); 31 | void set_offset(int offset); 32 | void set_name(string name); 33 | void set_type(int type); 34 | }; 35 | 36 | 37 | class Elf_File 38 | { 39 | public: 40 | static Elf32_Ehdr ehdr; 41 | static unordered_mapshdr_tab; 42 | static vectorshdr_name; 43 | static unordered_mapsym_tab; 44 | static vectorsym_name; 45 | static vectorrel_tab; 46 | 47 | static char* sh_str_tab; 48 | static int shstrtab_size; 49 | static char* str_tab; 50 | static int strtab_size; 51 | static vectorrel_text_tab; 52 | static vectorrel_data_tab; 53 | static FILE* fin; 54 | public: 55 | static void Init(); 56 | static int GetSegIndex(string seg_name); 57 | static int GetSymIndex(string sym_name); 58 | static void AddShdr(string name, int size, int data_length); 59 | static void AddShdr(string sh_name, Elf32_Word sh_type, Elf32_Word sh_flag, 60 | Elf32_Addr sh_addr, Elf32_Off sh_offset, Elf32_Word sh_size, 61 | Elf32_Word sh_link, Elf32_Word sh_info, Elf32_Word sh_addr_align, 62 | Elf32_Word sh_enter_size); 63 | static void AddSym(VarRecord* var); 64 | static void AddSym(string name, Elf32_Sym*); 65 | static Reloc* AddReloc(string seg, int addr, string name, int type); 66 | static void PaddingSeg(string prev,string next); 67 | static void AssembleObj(int data_length); 68 | static void WriteElfTail(); 69 | static void WriteElf(string name, int data_length, bool scan); 70 | static void Over(); 71 | }; 72 | 73 | -------------------------------------------------------------------------------- /Assembler/Generate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Generate.h" 4 | 5 | 6 | 7 | using namespace std; 8 | FILE* Generate::fout = nullptr; 9 | int Generate::total_length = 0; 10 | int Generate::error_number = 0; 11 | int Generate::line_number = 0; 12 | bool Generate::Init(string file_name) { 13 | line_number = 0; 14 | error_number = 0; 15 | total_length = 0; 16 | fout = nullptr; 17 | fout = fopen((file_name).c_str(), "wb"); 18 | if (fout != nullptr) { 19 | xSUCC("%s%s%s", "file[ ", file_name.c_str(), "] open[wb] successfully!\n"); 20 | return true; 21 | } 22 | else { 23 | xPANIC("%s%s%s", "file [", file_name.c_str(), "] open failed!\n"); 24 | return false; 25 | } 26 | 27 | } 28 | 29 | void Generate::WriteModRM(ModRM modrm,bool scan){ 30 | if (modrm.get_mod() != -1) { 31 | unsigned char mrm = (unsigned char)( 32 | ((modrm.get_mod() & 3) << 6) + 33 | ((modrm.get_reg() & 7) << 3) + 34 | (modrm.get_rm() & 7) 35 | ); 36 | WriteBytes(mrm, 1,scan); 37 | } 38 | } 39 | 40 | void Generate::WriteSIB(SIB sib, bool scan){ 41 | if (sib.get_scale() != -1){ 42 | unsigned char s = (unsigned char)( 43 | ((sib.get_scale() & 3) << 6) + 44 | ((sib.get_index() & 7) << 3) + 45 | (sib.get_base() & 7) 46 | ); 47 | WriteBytes(s, 1, scan); 48 | } 49 | } 50 | 51 | void Generate::WriteBytes(int value, int len, bool scan){ 52 | VarRecord::current_addr += len; 53 | if (!scan) { 54 | fwrite(&value, len, 1, fout); 55 | // fflush(fout); 56 | } 57 | return; 58 | } 59 | 60 | void Generate::WriteBytes(int value, int len) { 61 | fwrite(&value, len, 1, fout); 62 | // fflush(fout); 63 | } 64 | 65 | void Generate::WriteBytes(const void* buffer, size_t len) { 66 | fwrite(buffer, len, 1, fout); 67 | // fflush(fout); 68 | } 69 | 70 | bool Generate::HandleRelocation(int type, bool scan, VarRecord** rel,string cur_seg) { 71 | if (scan || (*rel) == nullptr) { 72 | (*rel) = nullptr; 73 | return false; 74 | } 75 | bool flag = false; 76 | if (type == R_386_32) { 77 | if (!(*rel)->get_is_equ()) { 78 | //obj 79 | Elf_File::AddReloc(cur_seg, VarRecord::current_addr, (*rel)->get_sym_name(), type); 80 | flag = true; 81 | } 82 | } 83 | else if (type == R_386_PC32) { 84 | if ((*rel)->get_is_externed()) { 85 | // obj 86 | Elf_File::AddReloc(cur_seg, VarRecord::current_addr, (*rel)->get_sym_name(), type); 87 | flag = true; 88 | } 89 | } 90 | (*rel) = nullptr; 91 | return flag; 92 | } 93 | 94 | void Generate::Generate2Op(symbol op, int des, int src, int len, Inst instructure, bool scan, VarRecord** rel, string cur_seg) { 95 | int index = -1; 96 | if (des == IMMD) { 97 | Error(immd_non_des); 98 | } 99 | else if (des == MEMO && src == MEMO) { 100 | Error(MEMO_non_both); 101 | } 102 | 103 | if (src == IMMD) index = 3; 104 | else index = (des - 2) * 2 + (src - 2); 105 | index = (op - rev_mov) * 8 + (1 - len % 4) * 4 + index; 106 | unsigned char op_code = op2code[index]; 107 | unsigned char ex_char; 108 | switch (instructure.mod_rm.get_mod()) { 109 | case -1: { 110 | // op [reg],imm 111 | switch (op) { 112 | case rev_mov: { 113 | op_code += (unsigned char)(instructure.mod_rm.get_reg()); 114 | WriteBytes(op_code, 1,scan); 115 | break; 116 | } 117 | case rev_cmp: { 118 | WriteBytes(op_code,1,scan); 119 | ex_char = 0xf8; 120 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 121 | WriteBytes(ex_char, 1, scan); 122 | break; 123 | } 124 | case rev_add: { 125 | WriteBytes(op_code, 1, scan); 126 | ex_char = 0xc0; 127 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 128 | WriteBytes(ex_char, 1, scan); 129 | break; 130 | } 131 | case rev_sub: { 132 | WriteBytes(op_code, 1, scan); 133 | ex_char = 0xe8; 134 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 135 | WriteBytes(ex_char, 1, scan); 136 | break; 137 | } 138 | } 139 | HandleRelocation(R_386_32, scan, rel, cur_seg); 140 | WriteBytes(instructure.get_imm32(), len, scan); 141 | break; 142 | } 143 | case 0: { 144 | WriteBytes(op_code, 1, scan); 145 | WriteModRM(instructure.mod_rm, scan); 146 | // op reg,[disp] | op [disp], reg 147 | if (instructure.mod_rm.get_rm() == 5) { 148 | HandleRelocation(R_386_32,scan,rel,cur_seg); 149 | instructure.WriteDisp(scan); 150 | } 151 | else if (instructure.mod_rm.get_rm() == 4) { 152 | WriteSIB(instructure.sib, scan); 153 | } 154 | break; 155 | } 156 | case 1: { 157 | // op [reg + disp8],reg | op reg [reg + disp8] 158 | WriteBytes(op_code, 1, scan); 159 | WriteModRM(instructure.mod_rm, scan); 160 | if (instructure.mod_rm.get_rm() == 4) 161 | WriteSIB(instructure.sib, scan); 162 | instructure.WriteDisp(scan); 163 | break; 164 | } 165 | case 2: { 166 | // op reg [reg + disp32] | op [reg + disp32],reg 167 | WriteBytes(op_code, 1, scan); 168 | WriteModRM(instructure.mod_rm, scan); 169 | if (instructure.mod_rm.get_rm() == 4) 170 | WriteSIB(instructure.sib,scan); 171 | instructure.WriteDisp(scan); 172 | break; 173 | } 174 | case 3: { 175 | // op reg,reg 176 | WriteBytes(op_code, 1, scan); 177 | WriteModRM(instructure.mod_rm, scan); 178 | break; 179 | } 180 | } 181 | } 182 | 183 | void Generate::Generate1Op(symbol op, int op_type, int len, Inst instructure, bool scan, VarRecord** relo, string cur_seg) { 184 | unsigned char ex_char; 185 | unsigned short int op_code = op1code[op - rev_call]; 186 | if (op == rev_call || op >= rev_jmp && op <= rev_jna) { 187 | if (op == rev_call || op == rev_jmp) { 188 | WriteBytes(op_code, 1, scan); 189 | } 190 | else { 191 | WriteBytes((op_code >> 8), 1, scan); 192 | WriteBytes(op_code, 1, scan); 193 | } 194 | int rel = instructure.get_imm32() - (VarRecord::current_addr + 4); 195 | bool ret_flag = HandleRelocation(R_386_PC32, scan, relo,cur_seg); 196 | if (ret_flag) rel = -4; 197 | WriteBytes(rel, 4,scan); 198 | return; 199 | } 200 | switch (op) { 201 | case rev_sys_int: { 202 | WriteBytes(op_code, 1, scan); 203 | WriteBytes(instructure.get_imm32(), 1, scan); 204 | break; 205 | } 206 | case rev_push: { 207 | if (op_type == IMMD) { 208 | op_code = 0x68; 209 | WriteBytes(op_code, 1, scan); 210 | WriteBytes(instructure.get_imm32(), 4, scan); 211 | } 212 | else 213 | { 214 | op_code += (unsigned char)(instructure.mod_rm.get_reg()); 215 | WriteBytes(op_code, 1, scan); 216 | } 217 | break; 218 | } 219 | case rev_inc: { 220 | if (len == 1) { 221 | op_code = 0xfe; 222 | WriteBytes(op_code, 1, scan); 223 | ex_char = 0xc0; 224 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 225 | WriteBytes(ex_char, 1, scan); 226 | } 227 | else { 228 | op_code += (unsigned char)(instructure.mod_rm.get_reg()); 229 | WriteBytes(op_code, 1, scan); 230 | } 231 | break; 232 | } 233 | case rev_dec: { 234 | if (len == 1) { 235 | op_code = 0xfe; 236 | WriteBytes(op_code, 1, scan); 237 | ex_char = 0xc8; 238 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 239 | WriteBytes(ex_char, 1, scan); 240 | } 241 | else { 242 | op_code += (unsigned char)(instructure.mod_rm.get_reg()); 243 | WriteBytes(op_code, 1, scan); 244 | } 245 | break; 246 | } 247 | case rev_neg: { 248 | if (len == 1) { 249 | op_code = 0xf6; 250 | } 251 | ex_char = 0xd8; 252 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 253 | WriteBytes(op_code, 1, scan); 254 | WriteBytes(ex_char, 1, scan); 255 | break; 256 | } 257 | case rev_pop: { 258 | op_code += (unsigned char)(instructure.mod_rm.get_reg()); 259 | WriteBytes(op_code, 1, scan); 260 | break; 261 | } 262 | case rev_imul: { 263 | WriteBytes(op_code, 1, scan); 264 | ex_char = 0xe8; 265 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 266 | WriteBytes(ex_char, 1, scan); 267 | break; 268 | } 269 | case rev_idiv: { 270 | WriteBytes(op_code, 1, scan); 271 | ex_char = 0xf8; 272 | ex_char += (unsigned char)(instructure.mod_rm.get_reg()); 273 | WriteBytes(ex_char, 1, scan); 274 | break; 275 | } 276 | } 277 | } 278 | 279 | void Generate::Generate0Op(symbol op,bool scan) { 280 | unsigned char op_code = op0code[0]; 281 | WriteBytes(op_code, 1, scan); 282 | } 283 | 284 | void Generate::Over() { 285 | line_number = 0; 286 | if (fout) { 287 | fclose(fout); 288 | fout = nullptr; 289 | } 290 | } 291 | 292 | void Generate::Error(error_c code) { 293 | error_number++; 294 | xPANIC("%s%d%s", "error at line [", line_number, "] "); 295 | switch (code) { 296 | case ident_lost:{ 297 | xWARN("%s", "ident may lost!\n"); 298 | break; 299 | } 300 | case times_wrong: { 301 | xWARN("%s", "`times` can only with number!\n"); 302 | break; 303 | } 304 | case equ_wrong: { 305 | xWARN("%s", "`equ` can only with number!\n"); 306 | break; 307 | } 308 | case len_type_wrong: { 309 | xWARN("%s", "type length only can be 1,2,4 (Byte)!\n"); 310 | break; 311 | } 312 | case type_wrong: { 313 | xWARN("%s", "type only can be db,dd,dw!\n"); 314 | } 315 | case comma_lost: { 316 | xWARN("%s", "comma(,) maybe lost!\n"); 317 | break; 318 | } 319 | case instruction_wrong: { 320 | xWARN("%s", "unrecognizied instruction!\n"); 321 | break; 322 | } 323 | case subs_non_number: { 324 | xWARN("%s", "sub(-) can only with number!\n"); 325 | break; 326 | } 327 | case regs_wrong: { 328 | xWARN("%s", "reister wrong! not an effective regs!\n"); 329 | break; 330 | } 331 | case rbrac_lost: { 332 | xWARN("%s", "rbrac(]) maybe lost!\n"); 333 | break; 334 | } 335 | case lbrac_lost: { 336 | xWARN("%s", "lbrac([) maybe lost!\n"); 337 | break; 338 | } 339 | } 340 | } -------------------------------------------------------------------------------- /Assembler/Generate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Common.h" 7 | #include "Semantic.h" 8 | 9 | class VarRecord; 10 | class SIB; 11 | class ModRM; 12 | class Inst; 13 | using namespace std; 14 | 15 | 16 | static unsigned char op2code[] = { 17 | /* 8 bit | 32 bit */ 18 | /* r,r r,m rm,r r,im| r,r r,m rm,r r,im */ 19 | 0x88,0x8a,0x88,0xb0,0x89,0x8b,0x89,0xb8, // mov 20 | 0x38,0x3a,0x38,0x80,0x39,0x3b,0x39,0x81, // cmp 21 | 0x28,0x2a,0x28,0x80,0x29,0x2b,0x29,0x81, // sub 22 | 0x00,0x02,0x00,0x80,0x01,0x03,0x01,0x81, // add 23 | 0x00,0x00,0x00,0x00,0x00,0x8d,0x00,0x00, // lea 24 | 0x20,0x22,0x20,0x80,0x21,0x23,0x21,0x81, // and 25 | 0x08,0x0a,0x08,0x80,0x0b,0x0b,0x09,0x81, // or 26 | }; 27 | 28 | static unsigned short op1code[] = { 29 | /* call int imul idiv neg inc dec jmp */ 30 | 0xe8,0xcd,0xf7,0xf7,0xf7,0x40,0x48,0xe9, 31 | /* je jg jl jge jle jne jna */ 32 | 0x0f84,0x0f8f,0x0f8c,0x0f8d,0x0f8e,0x0f85,0x0f86, 33 | /* push pop */ 34 | 0x50,0x58 35 | }; 36 | 37 | static unsigned char op0code[] = { 38 | /* ret */ 39 | 0xc3, 40 | }; 41 | 42 | class Generate{ 43 | private: 44 | static FILE* fout; 45 | static int total_length; 46 | public: 47 | static int error_number; 48 | static int line_number; 49 | public: 50 | static bool Init(string file_name); 51 | static void WriteModRM(ModRM modrm, bool scan); 52 | static void WriteSIB(SIB sib, bool scan); 53 | static void WriteBytes(int value, int len, bool scan); 54 | static void WriteBytes(int value, int len); 55 | static void WriteBytes(const void* buffer, size_t len); 56 | static bool HandleRelocation(int type, bool scan, VarRecord** rel, string cur_seg); 57 | static void Generate2Op(symbol op, int des, int src, int len, Inst instructure, bool scan, VarRecord** rel, string cur_seg); 58 | static void Generate1Op(symbol op, int op_type, int len, Inst instructure, bool scan, VarRecord** relo, string cur_seg); 59 | static void Generate0Op(symbol op, bool scan); 60 | static void Over(); 61 | static void Error(error_c code); 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /Assembler/Lexer.cpp: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | #include "Lexer.h" 3 | #include "Generate.h" 4 | 5 | 6 | Lexer::Lexer() { 7 | this->line_number = 0; 8 | this->current_char = ' '; 9 | this->old_char = ' '; 10 | this->fin = nullptr; 11 | this->num = 0; 12 | this->line_len = 0; 13 | this->position = 0; 14 | this->letter = 0; 15 | this->error_number = 0; 16 | this->sym = null; 17 | this->show_flag = false; 18 | memset(line, 0, MAX_LEN); 19 | memset(id, 0, ID_LEN + 1); 20 | memset(str, 0, STRING_LEN + 1); 21 | } 22 | 23 | Lexer::~Lexer() { 24 | Over(); 25 | } 26 | 27 | bool Lexer::Init(const char* file_path) { 28 | fin = fopen(file_path, "r"); 29 | if (fin) { 30 | xSUCC("%s%s%s", "file [", file_path, "] open[r] successfully!\n"); 31 | return true; 32 | } 33 | else { 34 | xPANIC("%s%s%s", "file [", file_path, "] open failed! not exist?\n"); 35 | return false; 36 | } 37 | } 38 | 39 | bool Lexer::GetChar() { 40 | if (position >= line_len) { 41 | position = 0; 42 | line_len = 0; 43 | line_number++; 44 | Generate::line_number++; 45 | current_char = ' '; 46 | while (current_char != '\n') { 47 | if (fscanf(fin, "%c", ¤t_char) == EOF) { 48 | line[line_len] = 0; 49 | break; 50 | } 51 | line[line_len] = current_char; 52 | line_len++; 53 | if (line_len == MAX_LEN) { 54 | LexerError(line2long); 55 | break; 56 | } 57 | } 58 | } 59 | old_char = current_char; 60 | current_char = line[position]; 61 | position++; 62 | if (current_char == 0) 63 | return false; 64 | else return true; 65 | } 66 | 67 | bool Lexer::GetSym() { 68 | while (current_char == ' ' || current_char == 10 || current_char == 9) { 69 | GetChar(); 70 | } 71 | if (current_char >= 'a' && current_char <= 'z' || 72 | current_char >= 'A' && current_char <= 'Z' || 73 | current_char == '_' || current_char == '@' || 74 | current_char == '.') { 75 | int id_length = 0; 76 | int real_length = 0; 77 | bool res_flag = true; 78 | do { 79 | real_length++; 80 | if (id_length = 'a' && current_char <= 'z' || 86 | current_char >= 'A' && current_char <= 'Z' || 87 | current_char == '_' || current_char == '@' || 88 | current_char == '.' || current_char >= '0' && current_char <= '9'); 89 | id[id_length] = 0; 90 | if (real_length > ID_LEN) { 91 | LexerError(id2long); 92 | } 93 | CheckReserved(); 94 | if (show_flag) sp(0); 95 | return res_flag; 96 | } 97 | else if (current_char >= '0' && current_char <= '9') { 98 | sym = number; 99 | int num_length = 0; 100 | num = 0; 101 | int real_length = 0; 102 | bool res_flag = true; 103 | do { 104 | real_length++; 105 | if (num_length < NUM_LENGTH) { 106 | num = 10 * num + (current_char - '0'); 107 | num_length++; 108 | } 109 | res_flag = GetChar(); 110 | } while (current_char >= '0' && current_char <= '9'); 111 | if (real_length > NUM_LENGTH) { 112 | LexerError(num2long); 113 | } 114 | if (show_flag) sp(1); 115 | return res_flag; 116 | } 117 | else { 118 | int str_length = 0; 119 | bool res_flag = true; 120 | int real_length = 0; 121 | switch (current_char) { 122 | case '+': { 123 | sym = addi; 124 | GET_CHAR 125 | if (show_flag) sp(3,"+"); 126 | break; 127 | } 128 | case '-': { 129 | sym = subs; 130 | GET_CHAR 131 | if (show_flag) sp(3, "-"); 132 | break; 133 | } 134 | case ':': { 135 | sym = colon; 136 | GET_CHAR 137 | if (show_flag) sp(3, ":"); 138 | break; 139 | } 140 | case ';': { 141 | sym = null; 142 | GET_CHAR 143 | while (current_char != '\n') { 144 | GET_CHAR 145 | } 146 | GET_CHAR 147 | break; 148 | } 149 | case ',': { 150 | sym = comma; 151 | GET_CHAR 152 | if (show_flag) sp(3, ","); 153 | break; 154 | } 155 | case'"': { 156 | sym = null; 157 | res_flag = GetChar(); 158 | real_length = 0; 159 | while (current_char != '"') { 160 | real_length++; 161 | if (str_length < STRING_LEN) { 162 | str[str_length] = current_char; 163 | str_length++; 164 | } 165 | res_flag = GetChar(); 166 | if (!res_flag) { 167 | LexerError(string_wrong); 168 | return false; 169 | } 170 | } 171 | str[str_length] = 0; 172 | if (real_length > STRING_LEN) { 173 | LexerError(str2long); 174 | } 175 | sym = strings; 176 | GET_CHAR 177 | if (show_flag) sp(2); 178 | break; 179 | } 180 | case '[': { 181 | sym = lbrac; 182 | GET_CHAR 183 | if (show_flag) sp(3, "["); 184 | break; 185 | } 186 | case']': { 187 | sym = rbrac; 188 | GET_CHAR 189 | if (show_flag) sp(3, "]"); 190 | break; 191 | } 192 | case 0: { 193 | sym = null; 194 | return false; 195 | } 196 | default: { 197 | LexerError(excep_sym); 198 | sym = excep; 199 | GET_CHAR 200 | break; 201 | } 202 | } 203 | } 204 | return true; 205 | } 206 | 207 | void Lexer::CheckReserved() { 208 | for (int i = 0; i < RESERVED_NUMBER; i++) { 209 | if (strcmp(id, reserved_table[i]) == 0) { 210 | sym = reserved_symbol[i]; 211 | return; 212 | } 213 | } 214 | sym = ident; 215 | return; 216 | } 217 | 218 | void Lexer::Over() { 219 | if (fin) { 220 | fclose(fin); 221 | fin = nullptr; 222 | } 223 | return; 224 | } 225 | 226 | char Lexer::get_current_char() { 227 | return current_char; 228 | } 229 | 230 | char Lexer::get_old_char() { 231 | return old_char; 232 | } 233 | 234 | int Lexer::get_line_number() { 235 | return line_number; 236 | } 237 | 238 | string Lexer::get_line() { 239 | return line; 240 | } 241 | 242 | int Lexer::get_position() { 243 | return position; 244 | } 245 | 246 | int Lexer::get_line_len() { 247 | return line_len; 248 | } 249 | 250 | string Lexer::get_id() { 251 | return id; 252 | } 253 | 254 | symbol Lexer::get_symbol() { 255 | return sym; 256 | } 257 | 258 | int Lexer::get_num() { 259 | return num; 260 | } 261 | 262 | char Lexer::get_letter() { 263 | return letter; 264 | } 265 | 266 | string Lexer::get_str() { 267 | return str; 268 | } 269 | 270 | int Lexer::get_error_number() { 271 | return error_number; 272 | } 273 | 274 | void Lexer::set_flag(bool show_flag) { 275 | this->show_flag = show_flag; 276 | } 277 | 278 | void Lexer::sp(int mode, string s) { 279 | cout << "line:" << line_number << " pos:" << position << " symbol is "; 280 | switch (mode) { 281 | case 0: { 282 | cout << id << endl; 283 | break; 284 | } 285 | case 1: { 286 | cout << num << endl; 287 | break; 288 | } 289 | case 2: { 290 | cout << str << endl; 291 | break; 292 | } 293 | default: { 294 | cout << s << endl; 295 | break; 296 | } 297 | } 298 | } 299 | 300 | void Lexer::LexerError(error_c code) { 301 | xPANIC("%s%d%s", "lexer error at line [", line_number, "]:"); 302 | switch (code){ 303 | case line2long: { 304 | xWARN("%s", "charactor at one line is too much!(over 80)\n"); 305 | break; 306 | } 307 | case id2long: { 308 | xWARN("%s", "ident name is too long!\n"); 309 | break; 310 | } 311 | case num2long: { 312 | xWARN("%s", "number is too big!\n"); 313 | break; 314 | } 315 | case str2long: { 316 | xWARN("%s", "string length is too long!\n"); 317 | break; 318 | } 319 | case excep_sym: { 320 | xWARN("%s", "not an effective symbol!\n"); 321 | break; 322 | } 323 | case string_wrong: { 324 | xWARN("%s", "string missing \"?\n"); 325 | break; 326 | } 327 | default: 328 | break; 329 | } 330 | } -------------------------------------------------------------------------------- /Assembler/Lexer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Common.h" 5 | #define GET_CHAR if(!GetChar()) return false; 6 | 7 | using namespace std; 8 | 9 | 10 | static enum symbol reserved_symbol[RESERVED_NUMBER]{ 11 | rev_al, rev_cl, rev_dl, rev_bl, 12 | rev_ah, rev_ch, rev_dh, rev_bh, 13 | rev_eax, rev_ecx, rev_edx, rev_ebx, 14 | rev_esp, rev_ebp, rev_esi, rev_edi, 15 | rev_mov, rev_cmp, rev_sub, rev_add, 16 | rev_lea,rev_and,rev_or,rev_call, rev_sys_int, rev_imul, 17 | rev_idiv,rev_neg, rev_inc, rev_dec, rev_jmp, 18 | rev_je, rev_jg, rev_jl, rev_jge, 19 | rev_jle, rev_jne, rev_jna, rev_push, 20 | rev_pop, rev_ret, rev_section, rev_global, 21 | rev_equ, rev_times, rev_db, rev_dw,rev_dd 22 | }; 23 | 24 | static char reserved_table[RESERVED_NUMBER][ID_LEN] = { 25 | al,cl,dl,bl, 26 | ah,ch,dh,bh, 27 | eax,ecx,edx,ebx, 28 | esp ,ebp,esi,edi, 29 | mov,cmp,sub,add, 30 | lea,land,lor,call,sys_int,imul, 31 | idiv,neg,inc,dec,jmp, 32 | je ,jg, jl ,jge, 33 | jle,jne,jna,_push, 34 | _pop,_ret,_section, 35 | global,equ,times, 36 | db,dw,dd 37 | }; 38 | 39 | class Lexer { 40 | 41 | private: 42 | char current_char; 43 | char old_char; 44 | int line_number; 45 | char line[MAX_LEN]; 46 | int position; 47 | int line_len; 48 | 49 | enum symbol sym; 50 | char id[ID_LEN + 1]; 51 | int num; 52 | char str[STRING_LEN + 1]; 53 | char letter; 54 | int error_number; 55 | FILE* fin; 56 | bool show_flag; 57 | 58 | public: 59 | Lexer(); 60 | ~Lexer(); 61 | bool Init(const char* file_name); 62 | void Over(); 63 | bool GetChar(); 64 | bool GetSym(); 65 | void CheckReserved(); 66 | // error handle 67 | void sp(int mode, string s = ""); 68 | void LexerError(error_c code); 69 | // set API 70 | char get_current_char(); 71 | char get_old_char(); 72 | int get_line_number(); 73 | string get_line(); 74 | int get_position(); 75 | int get_line_len(); 76 | string get_id(); 77 | symbol get_symbol(); 78 | int get_num(); 79 | char get_letter(); 80 | string get_str(); 81 | int get_error_number(); 82 | // set API 83 | void set_flag(bool show_flag); 84 | }; 85 | 86 | -------------------------------------------------------------------------------- /Assembler/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # make 3 | TOOL_PATH = ../make_tool/ 4 | 5 | MAKE = $(TOOL_PATH) make.exe -r 6 | SRC = main.cpp Generate.cpp Lexer.cpp Parser.cpp Semantic.cpp Elf_File.cpp 7 | SRC_H = Common.h Generate.h Lexer.h Parser.h Semantic.h elf.h Elf_File.h 8 | FLAGS = -g -Wno-deprecated -std=c++11 9 | # -g 编译产生调试信息 10 | # -Wno-deprecated 忽略头文件依赖的警告 11 | # -std=c++11 使用C++11 12 | # compile 13 | ass: $(SRC) $(SRC_H) Makefile 14 | g++ $(SRC) -o assembly.exe $(FLAGS) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Assembler/Parser.cpp: -------------------------------------------------------------------------------- 1 | #include "Parser.h" 2 | #include "Generate.h" 3 | 4 | 5 | void Parser::Init(const char* file_name) { 6 | this->rel_var = nullptr; 7 | this->wait = false; 8 | this->data_length = 0; 9 | this->cur_seg = ""; 10 | this->file_name = file_name; 11 | this->instructure.Init(); 12 | VarRecord::current_addr = 0x00000000; 13 | Table::var_map = unordered_map(); 14 | Table::def_labs = vector(); 15 | Table::set_scan_first(true); 16 | if (!lexer.Init(file_name)) 17 | exit(1); 18 | } 19 | 20 | bool Parser::NextToken() { 21 | if (wait) { 22 | wait = false; 23 | return true; 24 | } 25 | bool flag = false; 26 | while (true) { 27 | flag = lexer.GetSym(); 28 | if (lexer.get_symbol() == null || lexer.get_symbol() == excep) { 29 | if (!flag) { 30 | token = null; 31 | if (Table::get_scan_first()) { 32 | // table 33 | lexer.Over(); 34 | lexer = Lexer(); 35 | lexer.Init(file_name.c_str()); 36 | Table::SwtichSeg(data_length, cur_seg, lexer.get_id()); 37 | Table::set_scan_first(false); 38 | continue; 39 | } 40 | return false; 41 | } 42 | } 43 | else { 44 | token = lexer.get_symbol(); 45 | return true; 46 | } 47 | } 48 | } 49 | 50 | bool Parser::Match(symbol t) { 51 | return token == t; 52 | } 53 | 54 | void Parser::Program() { 55 | if (!NextToken() || token == null) { 56 | Table::ExportSym(); 57 | return; 58 | } 59 | else { 60 | string sym_name; 61 | switch(token) { 62 | case ident:{ 63 | sym_name = lexer.get_id(); 64 | IdentTail(sym_name); 65 | break; 66 | } 67 | case rev_section: { 68 | NextToken(); 69 | if (Match(ident)) { 70 | Table::SwtichSeg(data_length, cur_seg, lexer.get_id()); 71 | } 72 | else { 73 | Generate::Error(ident_lost); 74 | } 75 | break; 76 | } 77 | case rev_global: { 78 | NextToken(); 79 | if (!Match(ident)) { 80 | Generate::Error(ident_lost); 81 | } 82 | break; 83 | } 84 | default: { 85 | this->wait = true; 86 | Instruct(); 87 | break; 88 | } 89 | } 90 | Program(); 91 | } 92 | } 93 | 94 | void Parser::IdentTail(string name) { 95 | NextToken(); 96 | switch (token) { 97 | case rev_times:{ 98 | NextToken(); 99 | if (Match(number)) { 100 | BaeseTail(name,lexer.get_num()); 101 | } 102 | else { 103 | Generate::Error(times_wrong); 104 | } 105 | break; 106 | } 107 | case rev_equ: { 108 | NextToken(); 109 | if (Match(number)) { 110 | VarRecord* var = new VarRecord(name, lexer.get_num(),cur_seg); 111 | Table::AddVar(var); 112 | } 113 | else { 114 | Generate::Error(equ_wrong); 115 | } 116 | break; 117 | } 118 | case colon: { 119 | VarRecord* var = new VarRecord(name, false, cur_seg); 120 | Table::AddVar(var); 121 | break; 122 | } 123 | default: { 124 | this->wait = true; 125 | BaeseTail(name, 1); 126 | break; 127 | } 128 | } 129 | } 130 | 131 | void Parser::BaeseTail(string name, int num) { 132 | 133 | int length = Len(); 134 | Value(name, num, length); 135 | } 136 | 137 | int Parser::Len() { 138 | NextToken(); 139 | switch (token) { 140 | case rev_db: { 141 | return 1; 142 | } 143 | case rev_dw: { 144 | return 2; 145 | } 146 | case rev_dd: { 147 | return 4; 148 | } 149 | default: { 150 | Generate::Error(len_type_wrong); 151 | return 0; 152 | } 153 | } 154 | } 155 | 156 | void Parser::Value(string name, int time, int len) { 157 | int content[255] = { 0 }; 158 | int content_length = 0; 159 | Type(content, content_length, len); 160 | ValTail(content, content_length, len); 161 | VarRecord* var = new VarRecord(name, time, len, content, content_length, cur_seg); 162 | Table::AddVar(var); 163 | } 164 | 165 | void Parser::Type(int content[], int& content_len, int len) { 166 | NextToken(); 167 | switch (token) { 168 | case number:{ 169 | content[content_len] = lexer.get_num(); 170 | content_len++; 171 | break; 172 | } 173 | case strings: { 174 | string tmp = lexer.get_str(); 175 | for (int i = 0; iget_addr(); 185 | if (!Table::get_scan_first()) { 186 | if (!var->get_is_equ()) { 187 | Elf_File::AddReloc(cur_seg, VarRecord::current_addr + content_len * len, name, R_386_32); 188 | } 189 | } 190 | content_len++; 191 | break; 192 | } 193 | default: { 194 | Generate::Error(type_wrong); 195 | break; 196 | } 197 | } 198 | } 199 | 200 | void Parser::ValTail(int content[], int& content_len, int len) { 201 | NextToken(); 202 | if (token == comma) { 203 | Type(content, content_len, len); 204 | ValTail(content, content_len, len); 205 | } 206 | else { 207 | this->wait = true; 208 | } 209 | return; 210 | } 211 | 212 | void Parser::Instruct() { 213 | instructure.Init(); 214 | int len = 0; 215 | NextToken(); 216 | if (token >= rev_mov && token <= rev_or) { 217 | symbol op = token; 218 | int des_type = 0; 219 | int src_type = 0; 220 | int reg_num = 0; 221 | Operate(reg_num, des_type, len); 222 | NextToken(); 223 | if (Match(comma)) { 224 | Operate(reg_num, src_type, len); 225 | Generate::Generate2Op(op, des_type, src_type, len, instructure, Table::get_scan_first(), &rel_var, cur_seg); 226 | } 227 | else { 228 | Generate::Error(comma_lost); 229 | } 230 | } 231 | else if (token >= rev_call && token <= rev_pop) { 232 | symbol op = token; 233 | int type = 0; 234 | int reg_num = 0; 235 | Operate(reg_num, type, len); 236 | Generate::Generate1Op(op, type, len, instructure, Table::get_scan_first(), &rel_var, cur_seg); 237 | } 238 | else if (token == rev_ret) { 239 | symbol op = token; 240 | Generate::Generate0Op(op, Table::get_scan_first()); 241 | } 242 | else { 243 | Generate::Error(instruction_wrong); 244 | } 245 | } 246 | 247 | void Parser::Operate(int& reg_num, int& type, int& len) { 248 | string name = ""; 249 | VarRecord* var; 250 | NextToken(); 251 | switch (token) { 252 | case number: { 253 | type = IMMD; 254 | instructure.set_imm32(lexer.get_num()); 255 | break; 256 | } 257 | case ident: { 258 | type = IMMD; 259 | name = lexer.get_id(); 260 | var = Table::GetVar(name, cur_seg); 261 | instructure.set_imm32(var->get_addr()); 262 | if (!Table::get_scan_first()) { 263 | if (!var->get_is_equ()) { 264 | rel_var = var; 265 | } 266 | } 267 | break; 268 | } 269 | case lbrac: { 270 | type = MEMO; 271 | this->wait = true; 272 | Memory(); 273 | break; 274 | } 275 | case subs: { 276 | type = IMMD; 277 | NextToken(); 278 | if (Match(number)) { 279 | instructure.set_imm32(-lexer.get_num()); 280 | } 281 | else { 282 | Generate::Error(subs_non_number); 283 | } 284 | break; 285 | } 286 | default: { 287 | type = REGS; 288 | this->wait = true; 289 | len = Register(); 290 | if (reg_num != 0) { 291 | instructure.mod_rm.set_mod(3); 292 | instructure.mod_rm.set_rm(instructure.mod_rm.get_reg()); 293 | instructure.mod_rm.set_reg(token - rev_al - (1 - len % 4) * 8); 294 | } 295 | else { 296 | instructure.mod_rm.set_reg(token - rev_al - (1 - len % 4) * 8); 297 | } 298 | reg_num++; 299 | break; 300 | } 301 | } 302 | } 303 | 304 | int Parser::Register() { 305 | NextToken(); 306 | if (token >= rev_al && token <= rev_bh) { 307 | return 1; 308 | } 309 | else if (token >= rev_eax && token <= rev_edi) { 310 | return 4; 311 | } 312 | else { 313 | Generate::Error(regs_wrong); 314 | return 0; 315 | } 316 | } 317 | 318 | void Parser::Memory(){ 319 | NextToken(); 320 | if (Match(lbrac)) { 321 | Addr(); 322 | NextToken(); 323 | if (!Match(rbrac)) { 324 | Generate::Error(rbrac_lost); 325 | } 326 | } 327 | else { 328 | Generate::Error(lbrac_lost); 329 | } 330 | } 331 | 332 | void Parser::Addr(){ 333 | string name = ""; 334 | VarRecord* var; 335 | NextToken(); 336 | switch (token) { 337 | case number: { 338 | instructure.mod_rm.set_mod(0); 339 | instructure.mod_rm.set_rm(5); 340 | instructure.SetDisp(lexer.get_num(), 4); 341 | break; 342 | } 343 | case ident: { 344 | instructure.mod_rm.set_mod(0); 345 | instructure.mod_rm.set_rm(5); 346 | name = lexer.get_id(); 347 | var = Table::GetVar(name, cur_seg); 348 | instructure.SetDisp(var->get_addr(), 4); 349 | if (!Table::get_scan_first()) { 350 | if (!var->get_is_equ()) { 351 | rel_var = var; 352 | } 353 | } 354 | break; 355 | } 356 | default: { 357 | this->wait = true; 358 | int type = Register(); 359 | RegAddr(token, type); 360 | break; 361 | } 362 | } 363 | } 364 | 365 | void Parser::RegAddr(symbol base_reg, const int type){ 366 | NextToken(); 367 | if (token == addi || token == subs) { 368 | RegAddrTail(base_reg, type, token); 369 | } 370 | else { 371 | if (base_reg == rev_esp) { 372 | instructure.mod_rm.set_mod(0); 373 | instructure.mod_rm.set_rm(4); 374 | instructure.sib.set_scale(0); 375 | instructure.sib.set_index(4); 376 | instructure.sib.set_base(4); 377 | } 378 | else if (base_reg == rev_ebp) { 379 | instructure.mod_rm.set_mod(1); 380 | instructure.mod_rm.set_rm(5); 381 | instructure.SetDisp(0, 1); 382 | } 383 | else { 384 | instructure.mod_rm.set_mod(0); 385 | instructure.mod_rm.set_rm(base_reg - rev_al - (1 - type % 4) * 8); 386 | } 387 | this->wait = true; 388 | return; 389 | } 390 | } 391 | 392 | void Parser::RegAddrTail(symbol base_reg, const int type, symbol sign){ 393 | NextToken(); 394 | if (token == number) { 395 | int number = lexer.get_num(); 396 | if (sign == subs) { 397 | number = -number; 398 | } 399 | if (number >= -128 && number <= 128) { 400 | instructure.mod_rm.set_mod(1); 401 | instructure.SetDisp(number, 1); 402 | } 403 | else { 404 | instructure.mod_rm.set_mod(2); 405 | instructure.SetDisp(number, 4); 406 | } 407 | instructure.mod_rm.set_rm(base_reg - rev_al - (1 - type % 4) * 8); 408 | 409 | if (base_reg == rev_esp) { 410 | instructure.mod_rm.set_rm(4); 411 | instructure.sib.set_scale(0); 412 | instructure.sib.set_index(4); 413 | instructure.sib.set_base(4); 414 | } 415 | } 416 | else { 417 | this->wait = true; 418 | int type_reg = Register(); 419 | instructure.mod_rm.set_mod(0); 420 | instructure.mod_rm.set_rm(4); 421 | instructure.sib.set_scale(0); 422 | instructure.sib.set_index(token - rev_al - (1 - type_reg % 4) * 8); 423 | instructure.sib.set_base(base_reg - rev_al - (1 - type % 4) * 8); 424 | } 425 | } 426 | 427 | void Parser::Over() { 428 | Elf_File::WriteElf(file_name, data_length, Table::get_scan_first()); 429 | lexer.Over(); 430 | Generate::Over(); 431 | Table::Over(); 432 | Elf_File::Over(); 433 | 434 | xINFO("%s%d\n","error number:", Generate::error_number); 435 | if (Generate::error_number == 0) { 436 | xSUCC("%s%s%s", "assemble [", file_name.c_str(), "] successfully!\n"); 437 | } 438 | else { 439 | xPANIC("%s%s%s", "assmble [", file_name.c_str(), "] failed!\n"); 440 | } 441 | } 442 | 443 | Parser::~Parser() { 444 | lexer.Over(); 445 | Generate::Over(); 446 | Elf_File::Over(); 447 | } -------------------------------------------------------------------------------- /Assembler/Parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Common.h" 5 | #include "Semantic.h" 6 | #include "Lexer.h" 7 | 8 | using namespace std; 9 | 10 | class Parser 11 | { 12 | private: 13 | bool wait; 14 | enum symbol token; 15 | string cur_seg; 16 | int data_length; 17 | VarRecord* rel_var; 18 | Inst instructure; 19 | Lexer lexer; 20 | string file_name; 21 | public: 22 | ~Parser(); 23 | void Init(const char* file_name); 24 | bool NextToken(); 25 | bool Match(symbol t); 26 | void Program(); 27 | void IdentTail(string name); 28 | void BaeseTail(string name,int num); 29 | int Len(); 30 | void Value(string name, int time, int len); 31 | void Type(int content[], int& content_len, int len); 32 | void ValTail(int content[], int& content_len, int len); 33 | void Instruct(); 34 | void Operate(int& reg_num, int& type, int& len); 35 | int Register(); 36 | void Memory(); 37 | void Addr(); 38 | void RegAddr(symbol base_reg, const int type); 39 | void RegAddrTail(symbol base_reg, const int type, symbol sign); 40 | void Over(); 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /Assembler/Semantic.cpp: -------------------------------------------------------------------------------- 1 | #include "Semantic.h" 2 | 3 | 4 | 5 | int VarRecord::current_addr = 0x00000000; 6 | 7 | VarRecord::VarRecord(string name, bool externed,string cur_seg_name) { 8 | this->sym_name = name; 9 | this->addr = current_addr; 10 | this->is_externed = externed; 11 | this->is_equ = false; 12 | this->seg_name = cur_seg_name; 13 | this->time = 0; 14 | this->len_type = 0; 15 | this->sym_array = nullptr; 16 | this->sym_length = 0; 17 | if (externed) { 18 | this->addr = 0; 19 | seg_name = ""; 20 | } 21 | } 22 | 23 | VarRecord::VarRecord(string name, int addr,string cur_seg_name) { 24 | this->sym_name = name; 25 | this->is_equ = true; 26 | this->is_externed = false; 27 | this->seg_name = cur_seg_name; 28 | this->addr = addr; 29 | this->time = 0; 30 | this->len_type = 0; 31 | this->sym_array = nullptr; 32 | this->sym_length = 0; 33 | } 34 | 35 | VarRecord::VarRecord(string name, int time, int len_type, 36 | int content[], int content_len, string cur_seg_name) { 37 | this->sym_name = name; 38 | this->addr = current_addr; 39 | this->seg_name = cur_seg_name; 40 | this->is_equ = false; 41 | this->time = time; 42 | this->len_type = len_type; 43 | this->sym_length = content_len; 44 | this->sym_array = new int[content_len]; 45 | for (int i = 0; i < content_len; i++) { 46 | this->sym_array[i] = content[i]; 47 | } 48 | this->is_externed = false; 49 | current_addr += time * len_type * content_len; 50 | } 51 | 52 | void VarRecord::Write(bool scan) { 53 | for (int i = 0; i < time; i++) { 54 | for (int j = 0; j < sym_length; j++) { 55 | Generate::WriteBytes(sym_array[j], len_type, scan); 56 | } 57 | } 58 | } 59 | 60 | VarRecord::~VarRecord(){ 61 | if (sym_array) { 62 | delete[] sym_array; 63 | } 64 | } 65 | 66 | int VarRecord::get_current_addr() { 67 | return current_addr; 68 | } 69 | 70 | string VarRecord::get_seg_name() { 71 | return seg_name; 72 | } 73 | 74 | string VarRecord::get_sym_name() { 75 | return sym_name; 76 | } 77 | 78 | bool VarRecord::get_is_equ() { 79 | return is_equ; 80 | } 81 | 82 | bool VarRecord::get_is_externed() { 83 | return is_externed; 84 | } 85 | 86 | int VarRecord::get_times() { 87 | return time; 88 | } 89 | 90 | int VarRecord::get_addr() { 91 | return addr; 92 | } 93 | 94 | int VarRecord::get_len_type() { 95 | return len_type; 96 | } 97 | 98 | int VarRecord::get_sym_length() { 99 | return sym_length; 100 | } 101 | 102 | // ===================================================== 103 | unordered_mapTable::var_map = unordered_map(); 104 | vectorTable::def_labs = vector(); 105 | bool Table::scan_first = true; 106 | 107 | bool Table::HasName(string name) { 108 | return (var_map.find(name) != var_map.end()); 109 | } 110 | 111 | void Table::AddVar(VarRecord* var) { 112 | if (!scan_first) { 113 | delete var; 114 | return; 115 | } 116 | if (HasName(var->get_sym_name())) { 117 | if (var_map[var->get_sym_name()]->get_is_externed() && !var->get_is_externed()) { 118 | delete var_map[var->get_sym_name()]; 119 | var_map[var->get_sym_name()] = var; 120 | } 121 | } 122 | else { 123 | var_map[var->get_sym_name()] = var; 124 | } 125 | 126 | if (var->get_times() != 0 && var->get_seg_name() == DATA_SEG) { 127 | def_labs.push_back(var); 128 | } 129 | } 130 | 131 | VarRecord* Table::GetVar(string name,string cur_seg_name) { 132 | VarRecord* var; 133 | if (HasName(name)) { 134 | var = var_map[name]; 135 | } 136 | else { 137 | var_map[name] = new VarRecord(name, true, cur_seg_name); 138 | var = var_map[name]; 139 | } 140 | return var; 141 | } 142 | 143 | void Table::SwtichSeg(int& data_len, string& cur_seg_name,string seg_name) { 144 | if (scan_first) { 145 | data_len += (4 - data_len % 4) % 4; 146 | Elf_File::AddShdr(cur_seg_name, VarRecord::current_addr, data_len); 147 | if (cur_seg_name != ".bss") { 148 | data_len += VarRecord::current_addr; 149 | } 150 | } 151 | cur_seg_name = seg_name; 152 | VarRecord::current_addr = 0x00000000; 153 | } 154 | 155 | void Table::ExportSym() { 156 | unordered_map::iterator vi, vend; 157 | vend = var_map.end(); 158 | for (vi = var_map.begin(); vi != vend; vi++) { 159 | VarRecord* var = vi->second; 160 | if (!var->get_is_equ()) { 161 | Elf_File::AddSym(var); 162 | } 163 | } 164 | } 165 | 166 | void Table::Write(bool scan) { 167 | for (int i = 0; i < def_labs.size(); i++) { 168 | def_labs[i]->Write(scan); 169 | } 170 | } 171 | 172 | void Table::Over() { 173 | unordered_map::iterator vi, vend; 174 | vend = var_map.end(); 175 | for (vi = var_map.begin(); vi != vend; vi++) { 176 | delete vi->second; 177 | } 178 | var_map.clear(); 179 | def_labs.clear(); 180 | def_labs.shrink_to_fit(); 181 | } 182 | 183 | void Table::set_scan_first(bool scan) { 184 | scan_first = scan; 185 | } 186 | 187 | bool Table::get_scan_first() { 188 | return scan_first; 189 | } 190 | 191 | // ==================================================== 192 | ModRM::ModRM() { 193 | Init(); 194 | } 195 | 196 | void ModRM::Init() { 197 | this->mod = -1; 198 | this->reg = 0; 199 | this->rm = 0; 200 | } 201 | 202 | int ModRM::get_mod() { 203 | return this->mod; 204 | } 205 | 206 | int ModRM::get_reg() { 207 | return this->reg; 208 | } 209 | 210 | int ModRM::get_rm() { 211 | return this->rm; 212 | } 213 | 214 | void ModRM::set_mod(int mod) { 215 | this->mod = mod; 216 | } 217 | 218 | void ModRM::set_reg(int reg) { 219 | this->reg = reg; 220 | } 221 | 222 | void ModRM::set_rm(int rm) { 223 | this->rm = rm; 224 | } 225 | 226 | SIB::SIB() { 227 | Init(); 228 | } 229 | 230 | void SIB::Init() { 231 | this->scale = -1; 232 | this->index = 0; 233 | this->base = 0; 234 | } 235 | 236 | int SIB::get_scale() { 237 | return this->scale; 238 | } 239 | 240 | int SIB::get_index() { 241 | return this->index; 242 | } 243 | 244 | int SIB::get_base() { 245 | return this->base; 246 | } 247 | 248 | void SIB::set_scale(int scale) { 249 | this->scale = scale; 250 | } 251 | 252 | void SIB::set_index(int index) { 253 | this->index = index; 254 | } 255 | 256 | void SIB::set_base(int base) { 257 | this->base = base; 258 | } 259 | 260 | Inst::Inst() { 261 | Init(); 262 | } 263 | 264 | void Inst::Init() { 265 | this->opr = 0; 266 | this->disp = 0; 267 | this->disp_len = 0; 268 | this->imm32 = 0; 269 | this->mod_rm.Init(); 270 | this->sib.Init(); 271 | } 272 | 273 | void Inst::SetDisp(int disp,int len) { 274 | this->disp = disp; 275 | this->disp_len = len; 276 | } 277 | 278 | void Inst::WriteDisp(bool scan) { 279 | if (disp_len) { 280 | Generate::WriteBytes(disp, disp_len, scan); 281 | disp_len = 0; 282 | } 283 | } 284 | 285 | int Inst::get_imm32() { 286 | return this->imm32; 287 | } 288 | 289 | int Inst::get_disp(){ 290 | return this->disp; 291 | } 292 | 293 | int Inst::get_disp_len() { 294 | return this->disp_len; 295 | } 296 | 297 | unsigned char Inst::get_opr() { 298 | return this->opr; 299 | } 300 | 301 | void Inst::set_opr(unsigned char opr) { 302 | this->opr = opr; 303 | } 304 | 305 | void Inst::set_imm32(int imm32) { 306 | this->imm32 = imm32; 307 | } 308 | 309 | -------------------------------------------------------------------------------- /Assembler/Semantic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Elf_File.h" 7 | 8 | using namespace std; 9 | 10 | class VarRecord { 11 | private: 12 | string seg_name; 13 | string sym_name; 14 | bool is_equ; 15 | bool is_externed; 16 | int time; 17 | int addr; 18 | int len_type; 19 | int* sym_array; 20 | int sym_length; 21 | public: 22 | static int current_addr; 23 | VarRecord(string name,bool externed,string cur_seg_name); 24 | VarRecord(string name, int addr, string cur_seg_name); 25 | VarRecord(string name, int time, int len_type, int content[], int content_len, string cur_seg_name); 26 | void Write(bool scan); 27 | ~VarRecord(); 28 | // default API 29 | int get_current_addr(); 30 | string get_seg_name(); 31 | string get_sym_name(); 32 | bool get_is_equ(); 33 | bool get_is_externed(); 34 | int get_times(); 35 | int get_addr(); 36 | int get_len_type(); 37 | int get_sym_length(); 38 | }; 39 | 40 | class Table { 41 | public: 42 | static unordered_mapvar_map; 43 | static vectordef_labs; 44 | private: 45 | static bool scan_first; 46 | public: 47 | static bool HasName(string name); 48 | static void AddVar(VarRecord* var); 49 | static VarRecord* GetVar(string name, string cur_seg_name); 50 | static void SwtichSeg(int& data_len, string& cur_seg_name, string seg_name); 51 | static void ExportSym(); 52 | static void Write(bool scan); 53 | static void Over(); 54 | // default API 55 | static void set_scan_first(bool scan); 56 | static bool get_scan_first(); 57 | }; 58 | 59 | class ModRM { 60 | private: 61 | int mod; 62 | int reg; 63 | int rm; 64 | public: 65 | ModRM(); 66 | void Init(); 67 | // default API 68 | int get_mod(); 69 | int get_reg(); 70 | int get_rm(); 71 | void set_mod(int mod); 72 | void set_reg(int reg); 73 | void set_rm(int rm); 74 | }; 75 | 76 | class SIB { 77 | private: 78 | int scale; 79 | int index; 80 | int base; 81 | 82 | public: 83 | SIB(); 84 | void Init(); 85 | // default API 86 | int get_scale(); 87 | int get_index(); 88 | int get_base(); 89 | void set_scale(int scale); 90 | void set_index(int index); 91 | void set_base(int base); 92 | }; 93 | 94 | class Inst { 95 | private: 96 | unsigned char opr; 97 | int disp; 98 | int imm32; 99 | int disp_len; 100 | public: 101 | ModRM mod_rm; 102 | SIB sib; 103 | Inst(); 104 | void Init(); 105 | void SetDisp(int disp, int len); 106 | void WriteDisp(bool scan); 107 | // default API 108 | int get_imm32(); 109 | int get_disp(); 110 | int get_disp_len(); 111 | unsigned char get_opr(); 112 | void set_opr(unsigned char opr); 113 | void set_imm32(int imm32); 114 | }; -------------------------------------------------------------------------------- /Assembler/ass_test/common.s: -------------------------------------------------------------------------------- 1 | section .text 2 | @str2long: 3 | mov edx,@str2long_data_len 4 | mov ecx,@dtr2long_data 5 | mov ebx,1 6 | mov eax,4 7 | int 128 8 | mov ebx,0 9 | mov eax,1 10 | int 128 11 | ret 12 | @procBuf: 13 | mov esi,@buffer 14 | mov edi,0 15 | mov ecx,0 16 | mov eax,0 17 | mov ebx,10 18 | @cal_buf_len: 19 | mov cl,[esi+edi] 20 | cmp ecx,10 21 | je @cal_buf_len_exit 22 | inc edi 23 | imul ebx 24 | add eax,ecx 25 | sub eax,48 26 | jmp @cal_buf_len 27 | @cal_buf_len_exit: 28 | mov ecx,edi 29 | mov [@buffer_len],cl 30 | mov bl,[esi] 31 | ret 32 | global _start 33 | _start: 34 | call main 35 | mov ebx,0 36 | mov eax,1 37 | int 128 38 | ret 39 | section .data 40 | @dtr2long_data db "Str-Overflow",10,13 41 | @str2long_data_len equ 14 42 | @buffer times 255 db 0 43 | @buffer_len db 0 44 | @s_esp dd @s_base 45 | @s_ebp dd 0 46 | section .bss 47 | @s_stack times 65536 db 0 48 | @s_base: 49 | -------------------------------------------------------------------------------- /Assembler/ass_test/common.s.t: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Assembler/ass_test/common.s.t -------------------------------------------------------------------------------- /Assembler/ass_test/test.s: -------------------------------------------------------------------------------- 1 | section .text 2 | main: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 0 15 | push 0 16 | lea eax,[ebp-4] 17 | mov ebx,[ebp-8] 18 | mov [eax],ebx 19 | push 0 20 | push 0 21 | lea eax,[ebp-12] 22 | mov ebx,[ebp-16] 23 | mov [eax],ebx 24 | push 0 25 | lea eax,[ebp-12] 26 | mov ebx,[ebp-20] 27 | mov [eax],ebx 28 | @for_1_loop: 29 | push 10 30 | push 0 31 | mov eax,[ebp-12] 32 | mov ebx,[ebp-24] 33 | cmp eax,ebx 34 | jl @lab_base_cmp_6 35 | mov eax,0 36 | jmp @lab_base_cmp_exit_7 37 | @lab_base_cmp_6: 38 | mov eax,1 39 | @lab_base_cmp_exit_7: 40 | mov [ebp-28],eax 41 | mov eax,[ebp-28] 42 | cmp eax,0 43 | je @for_1_exit 44 | push 1 45 | push 0 46 | jmp @for_1_blcok 47 | @for_1_iter: 48 | mov eax,[ebp-12] 49 | mov ebx,[ebp-32] 50 | add eax,ebx 51 | mov [ebp-36],eax 52 | lea eax,[ebp-12] 53 | mov ebx,[ebp-36] 54 | mov [eax],ebx 55 | lea esp,[ebp-20] 56 | jmp @for_1_loop 57 | @for_1_blcok: 58 | push 0 59 | mov eax,[ebp-12] 60 | mov ebx,[ebp-12] 61 | imul ebx 62 | mov [ebp-40],eax 63 | push 0 64 | mov eax,[ebp-12] 65 | mov ebx,[ebp-40] 66 | imul ebx 67 | mov [ebp-44],eax 68 | lea eax,[ebp-4] 69 | mov ebx,[ebp-44] 70 | mov [eax],ebx 71 | push 1 72 | push -1 73 | mov eax,[@s_esp] 74 | mov [@s_esp],esp 75 | mov esp,eax 76 | mov eax,@str_1_len 77 | sub esp,1 78 | mov [esp],al 79 | mov [ebp-52],esp 80 | cmp eax,0 81 | je @lab_cpystr2_exit_15 82 | mov ecx,@str_1_len 83 | dec ecx 84 | mov esi,@str_1 85 | @lab_cpystr2_14: 86 | cmp ecx,-1 87 | je @lab_cpystr2_exit_15 88 | mov dl,[esi+ecx] 89 | sub esp,1 90 | mov [esp],dl 91 | dec ecx 92 | jmp @lab_cpystr2_14 93 | @lab_cpystr2_exit_15: 94 | mov eax,[@s_esp] 95 | mov [@s_esp],esp 96 | mov esp,eax 97 | mov eax,[@s_esp] 98 | mov [@s_esp],esp 99 | mov esp,eax 100 | mov eax,[ebp-4] 101 | mov esi,[ebp-52] 102 | mov edi,0 103 | cmp eax,0 104 | jge @lab_numsign1_exit_19 105 | @lab_numsign1_18: 106 | neg eax 107 | mov edi,1 108 | @lab_numsign1_exit_19: 109 | mov ebx,10 110 | @lab_num2str1_16: 111 | mov edx,0 112 | idiv ebx 113 | mov cl,[esi] 114 | inc cl 115 | mov [esi],cl 116 | sub esp,1 117 | add dl,48 118 | mov [esp],dl 119 | cmp eax,0 120 | jne @lab_num2str1_16 121 | cmp edi,0 122 | je @lab_numsign_add_20 123 | sub esp,1 124 | mov ecx,45 125 | mov [esp],cl 126 | mov cl,[esi] 127 | inc cl 128 | mov [esi],cl 129 | @lab_numsign_add_20: 130 | cmp cl,255 131 | jna @lab_num2str1_exit_17 132 | call @str2long 133 | @lab_num2str1_exit_17: 134 | mov eax,[@s_esp] 135 | mov [@s_esp],esp 136 | mov esp,eax 137 | push -1 138 | mov eax,[@s_esp] 139 | mov [@s_esp],esp 140 | mov esp,eax 141 | mov ebx,[ebp-52] 142 | mov eax,0 143 | mov al,[ebx] 144 | sub esp,1 145 | mov [esp],al 146 | mov [ebp-56],esp 147 | cmp eax,0 148 | je @lab_cpystr2_exit_23 149 | mov ecx,0 150 | mov esi,ebx 151 | dec esi 152 | neg eax 153 | @lab_cpystr2_22: 154 | cmp ecx,eax 155 | je @lab_cpystr2_exit_23 156 | mov dl,[esi+ecx] 157 | sub esp,1 158 | mov [esp],dl 159 | dec ecx 160 | jmp @lab_cpystr2_22 161 | @lab_cpystr2_exit_23: 162 | mov eax,[@s_esp] 163 | mov [@s_esp],esp 164 | mov esp,eax 165 | mov ecx,[ebp-56] 166 | mov edx,0 167 | mov dl,[ecx] 168 | sub ecx,edx 169 | mov ebx,1 170 | mov eax,4 171 | int 128 172 | jmp @for_1_iter 173 | @for_1_exit: 174 | push 0 175 | mov eax,[ebp-32] 176 | mov ebx,[@s_ebp] 177 | mov [@s_esp],ebx 178 | mov ebx,[@s_esp] 179 | mov [@s_esp],esp 180 | mov esp,ebx 181 | pop ebx 182 | mov [@s_ebp],ebx 183 | mov ebx,[@s_esp] 184 | mov [@s_esp],esp 185 | mov esp,ebx 186 | mov esp,ebp 187 | pop ebp 188 | ret 189 | section .data 190 | @str_1 db 10 191 | @str_1_len equ 1 192 | section .bss 193 | -------------------------------------------------------------------------------- /Assembler/ass_test/test.s.t: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Assembler/ass_test/test.s.t -------------------------------------------------------------------------------- /Assembler/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string.h" 3 | #include "Parser.h" 4 | #include "Generate.h" 5 | 6 | using namespace std; 7 | 8 | void Usage() { 9 | xWARN("%s", "Usage: ass file1 file2 ...\n"); 10 | } 11 | int main(int argc, char* argv[]) { 12 | if (argc < 2) { 13 | Usage(); 14 | } 15 | else if (strcmpi(argv[1], "ass") == 0) { 16 | for (int i = 2; i < argc; i++) { 17 | const char* path = argv[i]; 18 | Generate::Init(string(path) + ".t"); 19 | Elf_File::Init(); 20 | Parser parser; 21 | parser.Init(path); 22 | parser.Program(); 23 | parser.Over(); 24 | } 25 | } 26 | else { 27 | xPANIC("%s%s%s", "not recognize ", argv[1], ", using ass\n"); 28 | Usage(); 29 | 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Assembler/make.bat: -------------------------------------------------------------------------------- 1 | ..\make_tool\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 -------------------------------------------------------------------------------- /Compiler/Common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Common.h -------------------------------------------------------------------------------- /Compiler/Compiler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compiler", "Compiler.vcxproj", "{1AD2F910-63C0-4FDD-8F17-23A17300CCEE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Debug|x64.ActiveCfg = Debug|x64 17 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Debug|x64.Build.0 = Debug|x64 18 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Debug|x86.Build.0 = Debug|Win32 20 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Release|x64.ActiveCfg = Release|x64 21 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Release|x64.Build.0 = Release|x64 22 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Release|x86.ActiveCfg = Release|Win32 23 | {1AD2F910-63C0-4FDD-8F17-23A17300CCEE}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C96AC6B3-7701-4FC5-A9B0-CC00460A6866} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Compiler/Generator.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Generator.cpp -------------------------------------------------------------------------------- /Compiler/Generator.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Generator.h -------------------------------------------------------------------------------- /Compiler/Lexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Lexer.h" 3 | #include "Generator.h" 4 | 5 | Lexer::Lexer() { 6 | this->current_char = ' '; 7 | this->old_char = ' '; 8 | this->line_number = 0; 9 | this->position = 0; 10 | this->line_length = 0; 11 | this->letter = ' '; 12 | this->digit = 0; 13 | memset(this->line, 0, MAX_LEN); 14 | memset(this->id, 0, ID_LEN + 1); 15 | memset(this->str, 0, STRING_LEN); 16 | this->fin = nullptr; 17 | this->show_flag = false; 18 | this->error_number = 0; 19 | } 20 | 21 | bool Lexer::Init(const char* file_name) { 22 | fin = fopen(file_name, "r"); 23 | if (fin != nullptr) { 24 | xSUCC("%s%s%s", "file [", file_name, "] open successfully!\n"); 25 | return true; 26 | } 27 | else { 28 | xPANIC("%s%s%s", "file [", file_name, "] open failed!\n"); 29 | return false; 30 | } 31 | } 32 | 33 | bool Lexer::Getchar() { 34 | if (position >= line_length) { 35 | // read next line 36 | position = 0; 37 | line_length = 0; 38 | line_number++; 39 | Generator::line_number++; 40 | current_char = ' '; 41 | while (current_char != '\n') { 42 | if (fscanf(fin, "%c", ¤t_char) == EOF) { 43 | line[line_length] = 0; 44 | break; 45 | } 46 | line[line_length] = current_char; 47 | line_length++; 48 | if (line_length == MAX_LEN) { 49 | lexical_error(line2long); 50 | break; 51 | } 52 | } 53 | } 54 | 55 | old_char = current_char; 56 | current_char = line[position]; 57 | position++; 58 | if (current_char == 0) return false; 59 | else return true; 60 | } 61 | 62 | bool Lexer::GetSymbol() { 63 | while (current_char == ' ' || current_char == '\n' || current_char == 9) { 64 | Getchar(); 65 | } 66 | if (current_char >= 'a' && current_char <= 'z' || 67 | current_char >= 'A' && current_char <= 'Z' || 68 | current_char == '_') { 69 | int id_count = 0; // valid length 70 | int real_length = 0; // actural length 71 | bool result = false; 72 | do { 73 | real_length++; 74 | if (id_count < ID_LEN) { 75 | id[id_count] = current_char; 76 | id_count++; 77 | } 78 | result = Getchar(); 79 | } while (current_char >= 'a' && current_char <= 'z' || 80 | current_char >= 'A' && current_char <= 'Z' || 81 | current_char >= '0' && current_char <= '9' || 82 | current_char == '_'); 83 | id[id_count] = 0; 84 | if (real_length > ID_LEN) { 85 | lexical_error(id2long); 86 | } 87 | CheckReserved(); 88 | if (show_flag) sp(0); 89 | return result; 90 | } 91 | else if (current_char >= '0' && current_char <= '9') { 92 | sym = number; 93 | int num_count = 0; 94 | int real_length = 0; 95 | bool result = false; 96 | digit = 0; 97 | do{ 98 | real_length++; 99 | if (num_count < NUM_LEN) { 100 | digit = 10 * digit + (current_char - '0'); 101 | num_count++; 102 | } 103 | result = Getchar(); 104 | }while (current_char >= '0' && current_char <= '9'); 105 | if (real_length > NUM_LEN) { 106 | lexical_error(num2long); 107 | } 108 | if (show_flag) sp(3); 109 | return result; 110 | } 111 | else { 112 | int str_count = 0; 113 | int real_length = 0; 114 | bool result = false; 115 | switch (current_char) { 116 | case '+':{ 117 | sym = add; 118 | GETCHAR 119 | if (show_flag) sp(4, "+"); 120 | break; 121 | } 122 | case '-': { 123 | sym = sub; 124 | GETCHAR 125 | if (show_flag) sp(4, "-"); 126 | break; 127 | } 128 | case '*': { 129 | sym = mult; 130 | GETCHAR 131 | if (show_flag) sp(4, "*"); 132 | break; 133 | } 134 | case '/': { 135 | sym = divi; 136 | GETCHAR 137 | if (current_char == '/') { 138 | sym = null; 139 | while (current_char != '\n') { 140 | GETCHAR 141 | } 142 | GETCHAR 143 | } 144 | else if (current_char == '*') { 145 | sym = null; 146 | do { 147 | result = Getchar(); 148 | if (!result && current_char == 0 149 | && old_char == ' ') { 150 | lexical_error(annotation_wrong); 151 | return false; 152 | } 153 | if (current_char == '*') { 154 | result = Getchar(); 155 | if (!result && current_char == 0 156 | && old_char == ' ') { 157 | lexical_error(annotation_wrong); 158 | return false; 159 | } 160 | if (current_char == '/') break; 161 | } 162 | } while (true); 163 | GETCHAR 164 | } 165 | else if (show_flag) sp(4, "/"); 166 | break; 167 | } 168 | case '%': { 169 | sym = modi; 170 | GETCHAR 171 | if (show_flag) sp(4, "%"); 172 | break; 173 | } 174 | case '>': { 175 | sym = gt; 176 | GETCHAR 177 | if (current_char == '=') { 178 | sym = ge; 179 | if (show_flag) sp(4, ">="); 180 | GETCHAR 181 | } 182 | else if (current_char == '>') { 183 | sym = input; 184 | if (show_flag) sp(4, ">>"); 185 | GETCHAR 186 | } 187 | else if (show_flag) sp(4, ">"); 188 | break; 189 | } 190 | case '<': { 191 | sym = lt; 192 | GETCHAR 193 | if(current_char == '='){ 194 | sym = le; 195 | if (show_flag) sp(4, "<="); 196 | GETCHAR 197 | } 198 | else if (current_char == '<') { 199 | sym = output; 200 | if (show_flag) sp(4, "<<"); 201 | GETCHAR 202 | } 203 | else if (show_flag) sp(4, "<"); 204 | break; 205 | } 206 | case '=': { 207 | sym = assign; 208 | GETCHAR 209 | if(current_char == '='){ 210 | sym = equ; 211 | if (show_flag) sp(4, "=="); 212 | GETCHAR 213 | } 214 | if (show_flag) sp(4, "="); 215 | break; 216 | } 217 | case '!': { 218 | sym = null; 219 | GETCHAR 220 | if(current_char == '='){ 221 | sym = nequ; 222 | if (show_flag) sp(4, "!="); 223 | GETCHAR 224 | } 225 | break; 226 | } 227 | case ';': { 228 | sym = semicon; 229 | GETCHAR 230 | if (show_flag) sp(4, ";"); 231 | break; 232 | } 233 | case ',': { 234 | sym = comma; 235 | if (show_flag) sp(4, ","); 236 | GETCHAR 237 | break; 238 | } 239 | case '\'': { 240 | sym = null; 241 | result = Getchar(); 242 | if (!result) { 243 | lexical_error(char_wrong); 244 | return false; 245 | } 246 | letter = current_char; 247 | result = Getchar(); 248 | if (!result) { 249 | lexical_error(char_wrong); 250 | return false; 251 | } 252 | if (current_char == '\'') { 253 | sym = chara; 254 | if (show_flag) sp(2); 255 | GETCHAR 256 | } 257 | else { 258 | lexical_error(char_wrong); 259 | return false; 260 | } 261 | break; 262 | } 263 | case '"': { 264 | sym = null; 265 | result = Getchar(); 266 | if (!result) { 267 | lexical_error(string_wrong); 268 | return false; 269 | } 270 | real_length = 0; 271 | str_count = 0; 272 | while (current_char != '"') { 273 | real_length++; 274 | if (str_count < STRING_LEN) { 275 | if (current_char == '\\') { 276 | result = Getchar(); 277 | if (!result) { 278 | lexical_error(string_wrong); 279 | return false; 280 | } 281 | switch (current_char) { 282 | case 'n': str[str_count] = 10; break; 283 | case 't':str[str_count] = 9; break; 284 | default:str[str_count] = current_char; break; 285 | lexical_error(warn_escape); 286 | } 287 | } 288 | else if (current_char == '\n') { 289 | lexical_error(string_wrong); 290 | return false; 291 | } 292 | else { 293 | str[str_count] = current_char; 294 | } 295 | str_count++; 296 | } 297 | result = Getchar(); 298 | if (!result) { 299 | lexical_error(string_wrong); 300 | return false; 301 | } 302 | } 303 | str[str_count] = 0; 304 | if (real_length > STRING_LEN) { 305 | lexical_error(str2long); 306 | } 307 | sym = strings; 308 | if (show_flag) sp(1); 309 | GETCHAR 310 | break; 311 | } 312 | case '(': { 313 | sym = lparen; 314 | if (show_flag) sp(4, "("); 315 | GETCHAR 316 | break; 317 | } 318 | case ')': { 319 | sym = rparen; 320 | if (show_flag) sp(4, ")"); 321 | GETCHAR 322 | break; 323 | } 324 | case '{': { 325 | sym = lbrac; 326 | if (show_flag) sp(4, "{"); 327 | GETCHAR 328 | break; 329 | } 330 | case '}': { 331 | sym = rbrac; 332 | if (show_flag) sp(4, "}"); 333 | GETCHAR 334 | break; 335 | } 336 | case ':': { 337 | sym = colon; 338 | if (show_flag) sp(4, ":"); 339 | GETCHAR 340 | break; 341 | } 342 | case '|': { 343 | sym = null; 344 | GETCHAR 345 | if (current_char == '|') { 346 | sym = l_or; 347 | } 348 | GETCHAR 349 | break; 350 | } 351 | case '&': { 352 | sym = null; 353 | GETCHAR 354 | if(current_char == '&'){ 355 | sym = l_and; 356 | } 357 | GETCHAR 358 | break; 359 | } 360 | case 0: { 361 | sym = null; 362 | return false; 363 | } 364 | default: { 365 | sym = excep; 366 | lexical_error(expec_char); 367 | GETCHAR 368 | break; 369 | } 370 | } 371 | } 372 | return true; 373 | } 374 | 375 | void Lexer::CheckReserved() { 376 | int i = 0; 377 | int j = RESERVED_NUMBER - 1; 378 | int k = 0; 379 | for (; i <= j;) { 380 | k = (i + j) / 2; 381 | if (strcmp(id, reserved_table[k]) < 0) j = k - 1; 382 | else if (strcmp(id, reserved_table[k]) > 0) i = k + 1; 383 | else { 384 | sym = reserved_symbol[k]; 385 | break; 386 | } 387 | } 388 | if (i > j) sym = ident; 389 | return; 390 | } 391 | 392 | void Lexer::over() { 393 | if (fin) { 394 | fclose(fin); 395 | fin = nullptr; 396 | } 397 | return; 398 | } 399 | 400 | // other help API 401 | void Lexer::sp(int mode,string content) { 402 | cout << "line:" << line_number << " pos:" << position << "[" << symbol_name[sym] << "] is "; 403 | switch (mode) { 404 | case 0: { 405 | cout << id << endl; 406 | break; 407 | } 408 | case 1: { 409 | cout << str << endl; 410 | break; 411 | } 412 | case 2: { 413 | cout << letter << endl; 414 | break; 415 | } 416 | case 3: { 417 | cout << digit << endl; 418 | break; 419 | } 420 | default: { 421 | cout << content << endl; 422 | break; 423 | } 424 | } 425 | } 426 | 427 | void Lexer::lexical_error(enum error_c code) { 428 | Generator::error = true; 429 | if (code == warn_escape) { 430 | xWARN("%s%d%s%c%s", "warning[lexical warning at", line_number, "] escape failed with \\", current_char,"\n"); 431 | return; 432 | } 433 | error_number++; 434 | xPANIC("%s%d%s", "[lexical error at ", line_number, "] "); 435 | switch (code) { 436 | case char_wrong:{ 437 | xWARN("%s", "unrecognized char,miss ending '\n"); 438 | break; 439 | } 440 | case string_wrong: { 441 | xWARN("%s", "unrecognized string,miss ending \"\n"); 442 | break; 443 | } 444 | case annotation_wrong: { 445 | xWARN("%s", "annotation wrong missing ending * or /\n"); 446 | break; 447 | } 448 | case line2long: { 449 | xWARN("%s", "line over 80 charactors!\n"); 450 | break; 451 | } 452 | case str2long: { 453 | xWARN("%s%s%s", "string ", str, " is too long(over 255 byte)\n"); 454 | break; 455 | } 456 | case num2long: { 457 | xWARN("%s%d%s", "number ", digit, " is too long(over 999999999)\n"); 458 | break; 459 | } 460 | case id2long: { 461 | xWARN("%s%s%s", "ident ", id, " is too long(over 30 byte)\n"); 462 | break; 463 | } 464 | case expec_char: { 465 | xWARN("%s%c%s", "Unexpected symbol ", current_char, "\n"); 466 | break; 467 | } 468 | } 469 | } 470 | // default get API 471 | char Lexer::get_current_char() { 472 | return current_char; 473 | } 474 | 475 | char Lexer::get_old_char() { 476 | return old_char; 477 | } 478 | 479 | int Lexer::get_line_number() { 480 | return line_number; 481 | } 482 | 483 | int Lexer::get_position() { 484 | return position; 485 | } 486 | 487 | int Lexer::get_line_length() { 488 | return line_length; 489 | } 490 | 491 | symbol Lexer::get_sym() { 492 | return sym; 493 | } 494 | 495 | string Lexer::get_id() { 496 | return id; 497 | } 498 | 499 | string Lexer::get_str() { 500 | return str; 501 | } 502 | 503 | char Lexer::get_letter() { 504 | return letter; 505 | } 506 | 507 | int Lexer::get_digit() { 508 | return digit; 509 | } 510 | 511 | bool Lexer::get_show_flag() { 512 | return show_flag; 513 | } 514 | 515 | int Lexer::get_error_number() { 516 | return error_number; 517 | } 518 | // default set API 519 | 520 | void Lexer::set_show_flag(bool show_flag) { 521 | this->show_flag = show_flag; 522 | } 523 | 524 | Lexer::~Lexer() { 525 | over(); 526 | } -------------------------------------------------------------------------------- /Compiler/Lexer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Lexer.h -------------------------------------------------------------------------------- /Compiler/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # make 3 | TOOL_PATH = ../make_tool/ 4 | 5 | MAKE = $(TOOL_PATH) make.exe -r 6 | SRC = main.cpp Generator.cpp Lexer.cpp Parser.cpp Semantic.cpp 7 | SRC_H = common.h Generator.h Lexer.h Parser.h Semantic.h 8 | FLAGS = -g -Wno-deprecated -std=c++11 9 | # -g 编译产生调试信息 10 | # -Wno-deprecated 忽略头文件依赖的警告 11 | # -std=c++11 使用C++11 12 | # compile 13 | cc: $(SRC) $(SRC_H) Makefile 14 | g++ $(SRC) -o compile.exe $(FLAGS) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Compiler/Parser.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Parser.cpp -------------------------------------------------------------------------------- /Compiler/Parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Semantic.h" 5 | #include "Lexer.h" 6 | 7 | 8 | class Parser 9 | { 10 | private: 11 | VarRecord var; // Variable 12 | FunRecord fun; // function 13 | vectorbreak_level;// break in for or while? 14 | vectorcase_number;// case number 15 | Lexer lexer; // lexer 16 | bool wait; // skip read next token 17 | symbol old_token; 18 | symbol token; 19 | bool compiler_ok; 20 | int syntax_error; 21 | 22 | int while_id; 23 | int if_id; 24 | int for_id; 25 | int switch_id; 26 | bool ident_only; 27 | bool has_default; 28 | string file_name; 29 | 30 | public: 31 | Parser(); 32 | ~Parser(); 33 | void end(); 34 | void Init(const char* file_name); 35 | bool NextToken(); 36 | bool Match(symbol s); 37 | void Program(); 38 | void Dec(); 39 | symbol Type(); 40 | void DecTail(symbol type,string name); 41 | void FunTail(symbol type,string name); 42 | void VarList(symbol type); 43 | void Parameter(); 44 | void ParaList(); 45 | void Block(int init_number,int&level,int loop_id,int addr); 46 | void SubProgram(int& var_number, int& level, int loop_id, int addr); 47 | void LocalDec(int& var_number, int& level); 48 | void LocalDecTail(int& var_number, symbol type, int& level); 49 | void Statement(int& var_number, int& level, int loop_id, int addr); 50 | void WhileState(int& level); 51 | void IfState(int& level, int loop_id, int addr); 52 | 53 | void ForState(int& level); 54 | void ForInit(int& var_number, int& level); 55 | void ForCondition(int& var_number, int& level, int addr_end); 56 | void ForEnd(int& var_number, int& level, int loop_id, int addr, int addr_end); 57 | 58 | void SwitchState(int& level); 59 | void CaseState(int& level, int& init_number, int addr, VarRecord* var); 60 | 61 | void CaseHandle(VarRecord* var); 62 | void ReturnState(int& var_number, int& level); 63 | void ReturnTail(int& var_number, int& level); 64 | VarRecord* IdentTail(string name, int& var_number); 65 | void RealArgs(string name, int& var_number); 66 | void RealArgsList(int& var_number); 67 | 68 | VarRecord* OrExpr(int& var_number); 69 | VarRecord* OrExprTail(VarRecord* factor, int& var_number); 70 | VarRecord* Expr(int& var_number); 71 | VarRecord* ExprTail(VarRecord* factor, int& var_number); 72 | VarRecord* OneExpr(int& var_number); 73 | VarRecord* Item(int& var_number); 74 | VarRecord* ItemTail(VarRecord* factor, int& var_number); 75 | VarRecord* Factor(int& var_number); 76 | VarRecord* FactorTail(VarRecord* factor, int& var_number); 77 | 78 | void SyntaxError(error_c error_code); 79 | }; 80 | 81 | -------------------------------------------------------------------------------- /Compiler/Semantic.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/Compiler/Semantic.cpp -------------------------------------------------------------------------------- /Compiler/Semantic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Common.h" 7 | 8 | using namespace std; 9 | 10 | 11 | class VarRecord { 12 | private: 13 | symbol type; // type 14 | string name; // name 15 | int value; // value 16 | int local_addr; // relative with ebp 17 | bool externed; // is extern symbol? 18 | 19 | public: 20 | VarRecord(); 21 | VarRecord(const VarRecord& src); 22 | ~VarRecord() = default; 23 | void Init(symbol dec_type,string name); 24 | 25 | // get and set API 26 | symbol get_type(); 27 | string get_name(); 28 | int get_value(); 29 | int get_local_addr(); 30 | bool get_externed(); 31 | 32 | void set_type(symbol type); 33 | void set_name(string name); 34 | void set_value(int value); 35 | void set_local_addr(int addr); 36 | void set_externed(bool externed); 37 | 38 | }; 39 | 40 | 41 | class FunRecord { 42 | private: 43 | symbol type; 44 | string name; 45 | bool defined; 46 | bool flushed; 47 | bool has_return; 48 | 49 | public: 50 | vector* arguments; // arg type list 51 | vector* local_vars;// local var 52 | public: 53 | FunRecord(); 54 | FunRecord(const FunRecord& src); 55 | ~FunRecord(); 56 | void Init(symbol dec_type,string name); 57 | void AddArgs(VarRecord var); 58 | bool HasName(string name); 59 | void PushLocalVar(VarRecord var); 60 | int GetCurrentAddr(); 61 | void FlushArgs(); 62 | void PopLocalVars(int var_number); 63 | bool equal(FunRecord& function); 64 | VarRecord* CreateTmpVar(symbol type, bool has_val, int& var_number, 65 | string str="", int num=-1); 66 | 67 | // get and set API 68 | symbol get_type(); 69 | string get_name(); 70 | bool get_defined(); 71 | bool get_flushed(); 72 | bool get_has_return(); 73 | 74 | void set_defined(bool defined); 75 | void set_flushed(bool flushed); 76 | void set_has_return(bool has_return); 77 | 78 | }; 79 | 80 | 81 | class VarTable { 82 | private: 83 | static unordered_mapvar_map; // var 84 | static unordered_mapfun_map; // function 85 | static vectorstring_table; // string table 86 | static vectorparameter; // parameter list 87 | static int string_id; 88 | public: 89 | static bool syntax_error; // error 90 | public: 91 | static int AddString(string str); 92 | static string GetString(int index); 93 | static void AddVar(VarRecord& var); 94 | static void AddVar(VarRecord* var); 95 | static VarRecord* GetVar(string name, FunRecord& fun); 96 | static bool HasName(string name, FunRecord& fun); 97 | static void DelVar(string name); 98 | static void AddFun(FunRecord& fun); 99 | static void AddRealArgs(VarRecord* arg, int& var_number, FunRecord& fun); 100 | static VarRecord* GenerateCall(string fname, int& var_number, FunRecord& fun); 101 | static void over(); 102 | static void clear(); 103 | }; 104 | -------------------------------------------------------------------------------- /Compiler/common.s: -------------------------------------------------------------------------------- 1 | section .text 2 | section .data 3 | section .bss 4 | -------------------------------------------------------------------------------- /Compiler/compiler_test/test.s: -------------------------------------------------------------------------------- 1 | section .text 2 | main: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 0 15 | push 0 16 | lea eax,[ebp-4] 17 | mov ebx,[ebp-8] 18 | mov [eax],ebx 19 | push 0 20 | push 0 21 | lea eax,[ebp-12] 22 | mov ebx,[ebp-16] 23 | mov [eax],ebx 24 | push 0 25 | lea eax,[ebp-12] 26 | mov ebx,[ebp-20] 27 | mov [eax],ebx 28 | @for_1_loop: 29 | push 10 30 | push 0 31 | mov eax,[ebp-12] 32 | mov ebx,[ebp-24] 33 | cmp eax,ebx 34 | jl @lab_base_cmp_6 35 | mov eax,0 36 | jmp @lab_base_cmp_exit_7 37 | @lab_base_cmp_6: 38 | mov eax,1 39 | @lab_base_cmp_exit_7: 40 | mov [ebp-28],eax 41 | mov eax,[ebp-28] 42 | cmp eax,0 43 | je @for_1_exit 44 | push 1 45 | push 0 46 | jmp @for_1_blcok 47 | @for_1_iter: 48 | mov eax,[ebp-12] 49 | mov ebx,[ebp-32] 50 | add eax,ebx 51 | mov [ebp-36],eax 52 | lea eax,[ebp-12] 53 | mov ebx,[ebp-36] 54 | mov [eax],ebx 55 | lea esp,[ebp-20] 56 | jmp @for_1_loop 57 | @for_1_blcok: 58 | push 0 59 | mov eax,[ebp-12] 60 | mov ebx,[ebp-12] 61 | imul ebx 62 | mov [ebp-40],eax 63 | push 0 64 | mov eax,[ebp-12] 65 | mov ebx,[ebp-40] 66 | imul ebx 67 | mov [ebp-44],eax 68 | lea eax,[ebp-4] 69 | mov ebx,[ebp-44] 70 | mov [eax],ebx 71 | push 1 72 | push -1 73 | mov eax,[@s_esp] 74 | mov [@s_esp],esp 75 | mov esp,eax 76 | mov eax,@str_1_len 77 | sub esp,1 78 | mov [esp],al 79 | mov [ebp-52],esp 80 | cmp eax,0 81 | je @lab_cpystr2_exit_15 82 | mov ecx,@str_1_len 83 | dec ecx 84 | mov esi,@str_1 85 | @lab_cpystr2_14: 86 | cmp ecx,-1 87 | je @lab_cpystr2_exit_15 88 | mov dl,[esi+ecx] 89 | sub esp,1 90 | mov [esp],dl 91 | dec ecx 92 | jmp @lab_cpystr2_14 93 | @lab_cpystr2_exit_15: 94 | mov eax,[@s_esp] 95 | mov [@s_esp],esp 96 | mov esp,eax 97 | mov eax,[@s_esp] 98 | mov [@s_esp],esp 99 | mov esp,eax 100 | mov eax,[ebp-4] 101 | mov esi,[ebp-52] 102 | mov edi,0 103 | cmp eax,0 104 | jge @lab_numsign1_exit_19 105 | @lab_numsign1_18: 106 | neg eax 107 | mov edi,1 108 | @lab_numsign1_exit_19: 109 | mov ebx,10 110 | @lab_num2str1_16: 111 | mov edx,0 112 | idiv ebx 113 | mov cl,[esi] 114 | inc cl 115 | mov [esi],cl 116 | sub esp,1 117 | add dl,48 118 | mov [esp],dl 119 | cmp eax,0 120 | jne @lab_num2str1_16 121 | cmp edi,0 122 | je @lab_numsign_add_20 123 | sub esp,1 124 | mov ecx,45 125 | mov [esp],cl 126 | mov cl,[esi] 127 | inc cl 128 | mov [esi],cl 129 | @lab_numsign_add_20: 130 | cmp cl,255 131 | jna @lab_num2str1_exit_17 132 | call @str2long 133 | @lab_num2str1_exit_17: 134 | mov eax,[@s_esp] 135 | mov [@s_esp],esp 136 | mov esp,eax 137 | push -1 138 | mov eax,[@s_esp] 139 | mov [@s_esp],esp 140 | mov esp,eax 141 | mov ebx,[ebp-52] 142 | mov eax,0 143 | mov al,[ebx] 144 | sub esp,1 145 | mov [esp],al 146 | mov [ebp-56],esp 147 | cmp eax,0 148 | je @lab_cpystr2_exit_23 149 | mov ecx,0 150 | mov esi,ebx 151 | dec esi 152 | neg eax 153 | @lab_cpystr2_22: 154 | cmp ecx,eax 155 | je @lab_cpystr2_exit_23 156 | mov dl,[esi+ecx] 157 | sub esp,1 158 | mov [esp],dl 159 | dec ecx 160 | jmp @lab_cpystr2_22 161 | @lab_cpystr2_exit_23: 162 | mov eax,[@s_esp] 163 | mov [@s_esp],esp 164 | mov esp,eax 165 | mov ecx,[ebp-56] 166 | mov edx,0 167 | mov dl,[ecx] 168 | sub ecx,edx 169 | mov ebx,1 170 | mov eax,4 171 | int 128 172 | jmp @for_1_iter 173 | @for_1_exit: 174 | push 0 175 | mov eax,[ebp-32] 176 | mov ebx,[@s_ebp] 177 | mov [@s_esp],ebx 178 | mov ebx,[@s_esp] 179 | mov [@s_esp],esp 180 | mov esp,ebx 181 | pop ebx 182 | mov [@s_ebp],ebx 183 | mov ebx,[@s_esp] 184 | mov [@s_esp],esp 185 | mov esp,ebx 186 | mov esp,ebp 187 | pop ebp 188 | ret 189 | section .data 190 | @str_1 db 10 191 | @str_1_len equ 1 192 | section .bss 193 | -------------------------------------------------------------------------------- /Compiler/compiler_test/test.tc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int g = 0; 3 | int i=0; 4 | for(i=0;i < 10;i=i+1){ 5 | g = i * i * i; 6 | out << g + "\n"; 7 | } 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test1.s: -------------------------------------------------------------------------------- 1 | section .text 2 | main: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 0 15 | mov ecx,@buffer 16 | mov edx,255 17 | mov ebx,0 18 | mov eax,3 19 | int 128 20 | call @procBuf 21 | mov [ebp-4],eax 22 | push 2 23 | push -1 24 | mov eax,[@s_esp] 25 | mov [@s_esp],esp 26 | mov esp,eax 27 | mov eax,@str_2_len 28 | sub esp,1 29 | mov [esp],al 30 | mov [ebp-12],esp 31 | cmp eax,0 32 | je @lab_cpystr2_exit_30 33 | mov ecx,@str_2_len 34 | dec ecx 35 | mov esi,@str_2 36 | @lab_cpystr2_29: 37 | cmp ecx,-1 38 | je @lab_cpystr2_exit_30 39 | mov dl,[esi+ecx] 40 | sub esp,1 41 | mov [esp],dl 42 | dec ecx 43 | jmp @lab_cpystr2_29 44 | @lab_cpystr2_exit_30: 45 | mov eax,[@s_esp] 46 | mov [@s_esp],esp 47 | mov esp,eax 48 | mov ecx,[ebp-12] 49 | mov edx,0 50 | mov dl,[ecx] 51 | sub ecx,edx 52 | mov ebx,1 53 | mov eax,4 54 | int 128 55 | push -1 56 | mov eax,[@s_esp] 57 | mov [@s_esp],esp 58 | mov esp,eax 59 | mov eax,[ebp-4] 60 | sub esp,1 61 | mov ecx,0 62 | mov [esp],cl 63 | mov esi,esp 64 | mov [ebp-16],esp 65 | mov edi,0 66 | cmp eax,0 67 | jge @lab_numsign2_exit_37 68 | @lab_numsign2_36: 69 | neg eax 70 | mov edi,1 71 | @lab_numsign2_exit_37: 72 | mov ebx,10 73 | @lab_num2str2_34: 74 | mov edx,0 75 | idiv ebx 76 | mov cl,[esi] 77 | inc cl 78 | mov [esi],cl 79 | sub esp,1 80 | add dl,48 81 | mov [esp],dl 82 | cmp eax,0 83 | jne @lab_num2str2_34 84 | cmp edi,0 85 | je @lab_num2str2_exit_35 86 | sub esp,1 87 | mov ecx,45 88 | mov [esp],cl 89 | mov cl,[esi] 90 | inc cl 91 | mov [esi],cl 92 | @lab_num2str2_exit_35: 93 | mov eax,[@s_esp] 94 | mov [@s_esp],esp 95 | mov esp,eax 96 | mov ecx,[ebp-16] 97 | mov edx,0 98 | mov dl,[ecx] 99 | sub ecx,edx 100 | mov ebx,1 101 | mov eax,4 102 | int 128 103 | push 0 104 | mov eax,[ebp-20] 105 | mov ebx,[@s_ebp] 106 | mov [@s_esp],ebx 107 | mov ebx,[@s_esp] 108 | mov [@s_esp],esp 109 | mov esp,ebx 110 | pop ebx 111 | mov [@s_ebp],ebx 112 | mov ebx,[@s_esp] 113 | mov [@s_esp],esp 114 | mov esp,ebx 115 | mov esp,ebp 116 | pop ebp 117 | ret 118 | section .data 119 | @str_1 db "hello first test program",10 120 | @str_1_len equ 25 121 | section .bss 122 | -------------------------------------------------------------------------------- /Compiler/compiler_test/test1.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * just output something 3 | * first test case [right] 4 | */ 5 | int main(){ 6 | int a; 7 | in >> a; 8 | out << "hello first test program\n"; 9 | out << a; 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test2.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * Recursive function Fibonacci 3 | * second test case [right] 4 | */ 5 | 6 | int Fibonacci(int n); 7 | int main(){ 8 | int number; 9 | in >> number; 10 | int i = 1; 11 | int result = 1; 12 | // output the result 13 | for(i = 1; i < number; i = i + 1){ 14 | result = Fibonacci(i) 15 | out << result << "\n"; 16 | } 17 | return 0; 18 | } 19 | 20 | int Fibonacci(int n){ 21 | if(n == 1 || n == 0){ 22 | return 1; 23 | } 24 | else{ 25 | return Fibonacci(n - 1) + Fibonacci(n - 2); 26 | } 27 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test3.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * Annotation test 3 | * test case 3 [right] 4 | */ 5 | 6 | int main(){ 7 | /* [right] */ 8 | // /**/ [right] 9 | // /* .... */ 10 | /* 11 | * author : djh-sudo 12 | * date 2022/2/28 13 | * time 19:13 14 | */ 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test4.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * Annotation test 3 | * test case 4 [wrong] 4 | */ 5 | 6 | int main(){ 7 | /* * 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test5.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * test case 5 3 | * string and char test [wrong] 4 | * one line is too long! 5 | */ 6 | int main(){ 7 | string a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 8 | out << a; 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test6.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * test case 6 3 | * string and char test [wrong] 4 | * string missing the " 5 | */ 6 | int main(){ 7 | string a = "aaaaa; 8 | out << a; 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test7.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * test case 7 3 | * string and char test [wrong] 4 | * char missing the ' 5 | */ 6 | int main(){ 7 | char a = 'a; 8 | out << a; 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test8.s: -------------------------------------------------------------------------------- 1 | section .text 2 | main: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 0 15 | push 1 16 | push -1 17 | mov eax,[@s_esp] 18 | mov [@s_esp],esp 19 | mov esp,eax 20 | mov eax,@str_1_len 21 | sub esp,1 22 | mov [esp],al 23 | mov [ebp-12],esp 24 | cmp eax,0 25 | je @lab_cpystr2_exit_4 26 | mov ecx,@str_1_len 27 | dec ecx 28 | mov esi,@str_1 29 | @lab_cpystr2_3: 30 | cmp ecx,-1 31 | je @lab_cpystr2_exit_4 32 | mov dl,[esi+ecx] 33 | sub esp,1 34 | mov [esp],dl 35 | dec ecx 36 | jmp @lab_cpystr2_3 37 | @lab_cpystr2_exit_4: 38 | mov eax,[@s_esp] 39 | mov [@s_esp],esp 40 | mov esp,eax 41 | mov ecx,[ebp-12] 42 | mov edx,0 43 | mov dl,[ecx] 44 | sub ecx,edx 45 | mov ebx,1 46 | mov eax,4 47 | int 128 48 | mov ecx,@buffer 49 | mov edx,255 50 | mov ebx,0 51 | mov eax,3 52 | int 128 53 | call @procBuf 54 | mov [ebp-4],eax 55 | push 2 56 | push -1 57 | mov eax,[@s_esp] 58 | mov [@s_esp],esp 59 | mov esp,eax 60 | mov eax,@str_2_len 61 | sub esp,1 62 | mov [esp],al 63 | mov [ebp-20],esp 64 | cmp eax,0 65 | je @lab_cpystr2_exit_10 66 | mov ecx,@str_2_len 67 | dec ecx 68 | mov esi,@str_2 69 | @lab_cpystr2_9: 70 | cmp ecx,-1 71 | je @lab_cpystr2_exit_10 72 | mov dl,[esi+ecx] 73 | sub esp,1 74 | mov [esp],dl 75 | dec ecx 76 | jmp @lab_cpystr2_9 77 | @lab_cpystr2_exit_10: 78 | mov eax,[@s_esp] 79 | mov [@s_esp],esp 80 | mov esp,eax 81 | push 3 82 | push -1 83 | mov eax,[@s_esp] 84 | mov [@s_esp],esp 85 | mov esp,eax 86 | mov eax,@str_3_len 87 | sub esp,1 88 | mov [esp],al 89 | mov [ebp-28],esp 90 | cmp eax,0 91 | je @lab_cpystr2_exit_16 92 | mov ecx,@str_3_len 93 | dec ecx 94 | mov esi,@str_3 95 | @lab_cpystr2_15: 96 | cmp ecx,-1 97 | je @lab_cpystr2_exit_16 98 | mov dl,[esi+ecx] 99 | sub esp,1 100 | mov [esp],dl 101 | dec ecx 102 | jmp @lab_cpystr2_15 103 | @lab_cpystr2_exit_16: 104 | mov eax,[@s_esp] 105 | mov [@s_esp],esp 106 | mov esp,eax 107 | push 4 108 | push -1 109 | mov eax,[@s_esp] 110 | mov [@s_esp],esp 111 | mov esp,eax 112 | mov eax,@str_4_len 113 | sub esp,1 114 | mov [esp],al 115 | mov [ebp-36],esp 116 | cmp eax,0 117 | je @lab_cpystr2_exit_22 118 | mov ecx,@str_4_len 119 | dec ecx 120 | mov esi,@str_4 121 | @lab_cpystr2_21: 122 | cmp ecx,-1 123 | je @lab_cpystr2_exit_22 124 | mov dl,[esi+ecx] 125 | sub esp,1 126 | mov [esp],dl 127 | dec ecx 128 | jmp @lab_cpystr2_21 129 | @lab_cpystr2_exit_22: 130 | mov eax,[@s_esp] 131 | mov [@s_esp],esp 132 | mov esp,eax 133 | mov eax,[ebp-4] 134 | push eax 135 | mov eax,[ebp-36] 136 | push eax 137 | mov eax,[ebp-28] 138 | push eax 139 | mov eax,[ebp-20] 140 | push eax 141 | call hanoi 142 | add esp,16 143 | push 0 144 | mov eax,[ebp-40] 145 | mov ebx,[@s_ebp] 146 | mov [@s_esp],ebx 147 | mov ebx,[@s_esp] 148 | mov [@s_esp],esp 149 | mov esp,ebx 150 | pop ebx 151 | mov [@s_ebp],ebx 152 | mov ebx,[@s_esp] 153 | mov [@s_esp],esp 154 | mov esp,ebx 155 | mov esp,ebp 156 | pop ebp 157 | ret 158 | hanoi: 159 | push ebp 160 | mov ebp,esp 161 | mov ebx,[@s_esp] 162 | mov [@s_esp],esp 163 | mov esp,ebx 164 | mov ebx,[@s_ebp] 165 | push ebx 166 | mov [@s_ebp],esp 167 | mov ebx,[@s_esp] 168 | mov [@s_esp],esp 169 | mov esp,ebx 170 | push 0 171 | push 0 172 | mov eax,[ebp+20] 173 | mov ebx,[ebp-4] 174 | cmp eax,ebx 175 | je @lab_base_cmp_28 176 | mov eax,0 177 | jmp @lab_base_cmp_exit_29 178 | @lab_base_cmp_28: 179 | mov eax,1 180 | @lab_base_cmp_exit_29: 181 | mov [ebp-8],eax 182 | mov eax,[ebp-8] 183 | cmp eax,0 184 | je @if_1_middle 185 | mov ebx,[@s_ebp] 186 | mov [@s_esp],ebx 187 | mov ebx,[@s_esp] 188 | mov [@s_esp],esp 189 | mov esp,ebx 190 | pop ebx 191 | mov [@s_ebp],ebx 192 | mov ebx,[@s_esp] 193 | mov [@s_esp],esp 194 | mov esp,ebx 195 | mov esp,ebp 196 | pop ebp 197 | ret 198 | mov esp,ebp 199 | jmp @if_1_end 200 | @if_1_middle: 201 | mov esp,ebp 202 | push -1 203 | mov eax,[@s_esp] 204 | mov [@s_esp],esp 205 | mov esp,eax 206 | mov ebx,[ebp+8] 207 | mov eax,0 208 | mov al,[ebx] 209 | sub esp,1 210 | mov [esp],al 211 | mov [ebp-4],esp 212 | cmp eax,0 213 | je @lab_cpystr2_exit_32 214 | mov ecx,0 215 | mov esi,ebx 216 | dec esi 217 | neg eax 218 | @lab_cpystr2_31: 219 | cmp ecx,eax 220 | je @lab_cpystr2_exit_32 221 | mov dl,[esi+ecx] 222 | sub esp,1 223 | mov [esp],dl 224 | dec ecx 225 | jmp @lab_cpystr2_31 226 | @lab_cpystr2_exit_32: 227 | mov eax,[@s_esp] 228 | mov [@s_esp],esp 229 | mov esp,eax 230 | push -1 231 | mov eax,[@s_esp] 232 | mov [@s_esp],esp 233 | mov esp,eax 234 | mov ebx,[ebp+16] 235 | mov eax,0 236 | mov al,[ebx] 237 | sub esp,1 238 | mov [esp],al 239 | mov [ebp-8],esp 240 | cmp eax,0 241 | je @lab_cpystr2_exit_37 242 | mov ecx,0 243 | mov esi,ebx 244 | dec esi 245 | neg eax 246 | @lab_cpystr2_36: 247 | cmp ecx,eax 248 | je @lab_cpystr2_exit_37 249 | mov dl,[esi+ecx] 250 | sub esp,1 251 | mov [esp],dl 252 | dec ecx 253 | jmp @lab_cpystr2_36 254 | @lab_cpystr2_exit_37: 255 | mov eax,[@s_esp] 256 | mov [@s_esp],esp 257 | mov esp,eax 258 | push -1 259 | mov eax,[@s_esp] 260 | mov [@s_esp],esp 261 | mov esp,eax 262 | mov ebx,[ebp+12] 263 | mov eax,0 264 | mov al,[ebx] 265 | sub esp,1 266 | mov [esp],al 267 | mov [ebp-12],esp 268 | cmp eax,0 269 | je @lab_cpystr2_exit_42 270 | mov ecx,0 271 | mov esi,ebx 272 | dec esi 273 | neg eax 274 | @lab_cpystr2_41: 275 | cmp ecx,eax 276 | je @lab_cpystr2_exit_42 277 | mov dl,[esi+ecx] 278 | sub esp,1 279 | mov [esp],dl 280 | dec ecx 281 | jmp @lab_cpystr2_41 282 | @lab_cpystr2_exit_42: 283 | mov eax,[@s_esp] 284 | mov [@s_esp],esp 285 | mov esp,eax 286 | push 1 287 | push 0 288 | mov eax,[ebp+20] 289 | mov ebx,[ebp-16] 290 | sub eax,ebx 291 | mov [ebp-20],eax 292 | mov eax,[ebp-20] 293 | push eax 294 | mov eax,[ebp-12] 295 | push eax 296 | mov eax,[ebp-8] 297 | push eax 298 | mov eax,[ebp-4] 299 | push eax 300 | call hanoi 301 | add esp,16 302 | push 5 303 | push 6 304 | push 7 305 | push 8 306 | push -1 307 | mov eax,[@s_esp] 308 | mov [@s_esp],esp 309 | mov esp,eax 310 | mov eax,@str_8_len 311 | sub esp,1 312 | mov [esp],al 313 | mov [ebp-40],esp 314 | cmp eax,0 315 | je @lab_cpystr2_exit_53 316 | mov ecx,@str_8_len 317 | dec ecx 318 | mov esi,@str_8 319 | @lab_cpystr2_52: 320 | cmp ecx,-1 321 | je @lab_cpystr2_exit_53 322 | mov dl,[esi+ecx] 323 | sub esp,1 324 | mov [esp],dl 325 | dec ecx 326 | jmp @lab_cpystr2_52 327 | @lab_cpystr2_exit_53: 328 | mov eax,[@s_esp] 329 | mov [@s_esp],esp 330 | mov esp,eax 331 | mov eax,[@s_esp] 332 | mov [@s_esp],esp 333 | mov esp,eax 334 | mov ebx,[ebp+16] 335 | mov eax,0 336 | mov al,[ebx] 337 | cmp eax,0 338 | je @lab_cpystr1_exit_55 339 | mov ebx,[ebp-40] 340 | mov edx,0 341 | mov dl,[ebx] 342 | add edx,eax 343 | mov [ebx],dl 344 | mov ecx,0 345 | mov esi,[ebp+16] 346 | sub esi,1 347 | neg eax 348 | cmp edx,255 349 | jna @lab_cpystr1_54 350 | call @str2long 351 | @lab_cpystr1_54: 352 | cmp ecx,eax 353 | je @lab_cpystr1_exit_55 354 | mov dl,[esi+ecx] 355 | sub esp,1 356 | mov [esp],dl 357 | dec ecx 358 | jmp @lab_cpystr1_54 359 | @lab_cpystr1_exit_55: 360 | mov eax,[@s_esp] 361 | mov [@s_esp],esp 362 | mov esp,eax 363 | push -1 364 | mov eax,[@s_esp] 365 | mov [@s_esp],esp 366 | mov esp,eax 367 | mov ebx,[ebp-40] 368 | mov eax,0 369 | mov al,[ebx] 370 | sub esp,1 371 | mov [esp],al 372 | mov [ebp-44],esp 373 | cmp eax,0 374 | je @lab_cpystr2_exit_58 375 | mov ecx,0 376 | mov esi,ebx 377 | dec esi 378 | neg eax 379 | @lab_cpystr2_57: 380 | cmp ecx,eax 381 | je @lab_cpystr2_exit_58 382 | mov dl,[esi+ecx] 383 | sub esp,1 384 | mov [esp],dl 385 | dec ecx 386 | jmp @lab_cpystr2_57 387 | @lab_cpystr2_exit_58: 388 | mov eax,[@s_esp] 389 | mov [@s_esp],esp 390 | mov esp,eax 391 | mov eax,[@s_esp] 392 | mov [@s_esp],esp 393 | mov esp,eax 394 | mov eax,@str_7_len 395 | cmp eax,0 396 | je @lab_cpystr1_exit_60 397 | mov ebx,[ebp-44] 398 | mov edx,0 399 | mov dl,[ebx] 400 | add edx,eax 401 | mov [ebx],dl 402 | mov ecx,@str_7_len 403 | dec ecx 404 | mov esi,@str_7 405 | cmp edx,255 406 | jna @lab_cpystr1_59 407 | call @str2long 408 | @lab_cpystr1_59: 409 | cmp ecx,-1 410 | je @lab_cpystr1_exit_60 411 | mov al,[esi+ecx] 412 | sub esp,1 413 | mov [esp],al 414 | dec ecx 415 | jmp @lab_cpystr1_59 416 | @lab_cpystr1_exit_60: 417 | mov eax,[@s_esp] 418 | mov [@s_esp],esp 419 | mov esp,eax 420 | push -1 421 | mov eax,[@s_esp] 422 | mov [@s_esp],esp 423 | mov esp,eax 424 | mov ebx,[ebp-44] 425 | mov eax,0 426 | mov al,[ebx] 427 | sub esp,1 428 | mov [esp],al 429 | mov [ebp-48],esp 430 | cmp eax,0 431 | je @lab_cpystr2_exit_63 432 | mov ecx,0 433 | mov esi,ebx 434 | dec esi 435 | neg eax 436 | @lab_cpystr2_62: 437 | cmp ecx,eax 438 | je @lab_cpystr2_exit_63 439 | mov dl,[esi+ecx] 440 | sub esp,1 441 | mov [esp],dl 442 | dec ecx 443 | jmp @lab_cpystr2_62 444 | @lab_cpystr2_exit_63: 445 | mov eax,[@s_esp] 446 | mov [@s_esp],esp 447 | mov esp,eax 448 | mov eax,[@s_esp] 449 | mov [@s_esp],esp 450 | mov esp,eax 451 | mov ebx,[ebp+8] 452 | mov eax,0 453 | mov al,[ebx] 454 | cmp eax,0 455 | je @lab_cpystr1_exit_65 456 | mov ebx,[ebp-48] 457 | mov edx,0 458 | mov dl,[ebx] 459 | add edx,eax 460 | mov [ebx],dl 461 | mov ecx,0 462 | mov esi,[ebp+8] 463 | sub esi,1 464 | neg eax 465 | cmp edx,255 466 | jna @lab_cpystr1_64 467 | call @str2long 468 | @lab_cpystr1_64: 469 | cmp ecx,eax 470 | je @lab_cpystr1_exit_65 471 | mov dl,[esi+ecx] 472 | sub esp,1 473 | mov [esp],dl 474 | dec ecx 475 | jmp @lab_cpystr1_64 476 | @lab_cpystr1_exit_65: 477 | mov eax,[@s_esp] 478 | mov [@s_esp],esp 479 | mov esp,eax 480 | push -1 481 | mov eax,[@s_esp] 482 | mov [@s_esp],esp 483 | mov esp,eax 484 | mov ebx,[ebp-48] 485 | mov eax,0 486 | mov al,[ebx] 487 | sub esp,1 488 | mov [esp],al 489 | mov [ebp-52],esp 490 | cmp eax,0 491 | je @lab_cpystr2_exit_68 492 | mov ecx,0 493 | mov esi,ebx 494 | dec esi 495 | neg eax 496 | @lab_cpystr2_67: 497 | cmp ecx,eax 498 | je @lab_cpystr2_exit_68 499 | mov dl,[esi+ecx] 500 | sub esp,1 501 | mov [esp],dl 502 | dec ecx 503 | jmp @lab_cpystr2_67 504 | @lab_cpystr2_exit_68: 505 | mov eax,[@s_esp] 506 | mov [@s_esp],esp 507 | mov esp,eax 508 | mov eax,[@s_esp] 509 | mov [@s_esp],esp 510 | mov esp,eax 511 | mov eax,@str_6_len 512 | cmp eax,0 513 | je @lab_cpystr1_exit_70 514 | mov ebx,[ebp-52] 515 | mov edx,0 516 | mov dl,[ebx] 517 | add edx,eax 518 | mov [ebx],dl 519 | mov ecx,@str_6_len 520 | dec ecx 521 | mov esi,@str_6 522 | cmp edx,255 523 | jna @lab_cpystr1_69 524 | call @str2long 525 | @lab_cpystr1_69: 526 | cmp ecx,-1 527 | je @lab_cpystr1_exit_70 528 | mov al,[esi+ecx] 529 | sub esp,1 530 | mov [esp],al 531 | dec ecx 532 | jmp @lab_cpystr1_69 533 | @lab_cpystr1_exit_70: 534 | mov eax,[@s_esp] 535 | mov [@s_esp],esp 536 | mov esp,eax 537 | push -1 538 | mov eax,[@s_esp] 539 | mov [@s_esp],esp 540 | mov esp,eax 541 | mov ebx,[ebp-52] 542 | mov eax,0 543 | mov al,[ebx] 544 | sub esp,1 545 | mov [esp],al 546 | mov [ebp-56],esp 547 | cmp eax,0 548 | je @lab_cpystr2_exit_73 549 | mov ecx,0 550 | mov esi,ebx 551 | dec esi 552 | neg eax 553 | @lab_cpystr2_72: 554 | cmp ecx,eax 555 | je @lab_cpystr2_exit_73 556 | mov dl,[esi+ecx] 557 | sub esp,1 558 | mov [esp],dl 559 | dec ecx 560 | jmp @lab_cpystr2_72 561 | @lab_cpystr2_exit_73: 562 | mov eax,[@s_esp] 563 | mov [@s_esp],esp 564 | mov esp,eax 565 | mov eax,[@s_esp] 566 | mov [@s_esp],esp 567 | mov esp,eax 568 | mov eax,[ebp+20] 569 | mov esi,[ebp-56] 570 | mov edi,0 571 | cmp eax,0 572 | jge @lab_numsign1_exit_77 573 | @lab_numsign1_76: 574 | neg eax 575 | mov edi,1 576 | @lab_numsign1_exit_77: 577 | mov ebx,10 578 | @lab_num2str1_74: 579 | mov edx,0 580 | idiv ebx 581 | mov cl,[esi] 582 | inc cl 583 | mov [esi],cl 584 | sub esp,1 585 | add dl,48 586 | mov [esp],dl 587 | cmp eax,0 588 | jne @lab_num2str1_74 589 | cmp edi,0 590 | je @lab_numsign_add_78 591 | sub esp,1 592 | mov ecx,45 593 | mov [esp],cl 594 | mov cl,[esi] 595 | inc cl 596 | mov [esi],cl 597 | @lab_numsign_add_78: 598 | cmp cl,255 599 | jna @lab_num2str1_exit_75 600 | call @str2long 601 | @lab_num2str1_exit_75: 602 | mov eax,[@s_esp] 603 | mov [@s_esp],esp 604 | mov esp,eax 605 | push -1 606 | mov eax,[@s_esp] 607 | mov [@s_esp],esp 608 | mov esp,eax 609 | mov ebx,[ebp-56] 610 | mov eax,0 611 | mov al,[ebx] 612 | sub esp,1 613 | mov [esp],al 614 | mov [ebp-60],esp 615 | cmp eax,0 616 | je @lab_cpystr2_exit_81 617 | mov ecx,0 618 | mov esi,ebx 619 | dec esi 620 | neg eax 621 | @lab_cpystr2_80: 622 | cmp ecx,eax 623 | je @lab_cpystr2_exit_81 624 | mov dl,[esi+ecx] 625 | sub esp,1 626 | mov [esp],dl 627 | dec ecx 628 | jmp @lab_cpystr2_80 629 | @lab_cpystr2_exit_81: 630 | mov eax,[@s_esp] 631 | mov [@s_esp],esp 632 | mov esp,eax 633 | mov eax,[@s_esp] 634 | mov [@s_esp],esp 635 | mov esp,eax 636 | mov eax,@str_5_len 637 | cmp eax,0 638 | je @lab_cpystr1_exit_83 639 | mov ebx,[ebp-60] 640 | mov edx,0 641 | mov dl,[ebx] 642 | add edx,eax 643 | mov [ebx],dl 644 | mov ecx,@str_5_len 645 | dec ecx 646 | mov esi,@str_5 647 | cmp edx,255 648 | jna @lab_cpystr1_82 649 | call @str2long 650 | @lab_cpystr1_82: 651 | cmp ecx,-1 652 | je @lab_cpystr1_exit_83 653 | mov al,[esi+ecx] 654 | sub esp,1 655 | mov [esp],al 656 | dec ecx 657 | jmp @lab_cpystr1_82 658 | @lab_cpystr1_exit_83: 659 | mov eax,[@s_esp] 660 | mov [@s_esp],esp 661 | mov esp,eax 662 | push -1 663 | mov eax,[@s_esp] 664 | mov [@s_esp],esp 665 | mov esp,eax 666 | mov ebx,[ebp-60] 667 | mov eax,0 668 | mov al,[ebx] 669 | sub esp,1 670 | mov [esp],al 671 | mov [ebp-64],esp 672 | cmp eax,0 673 | je @lab_cpystr2_exit_86 674 | mov ecx,0 675 | mov esi,ebx 676 | dec esi 677 | neg eax 678 | @lab_cpystr2_85: 679 | cmp ecx,eax 680 | je @lab_cpystr2_exit_86 681 | mov dl,[esi+ecx] 682 | sub esp,1 683 | mov [esp],dl 684 | dec ecx 685 | jmp @lab_cpystr2_85 686 | @lab_cpystr2_exit_86: 687 | mov eax,[@s_esp] 688 | mov [@s_esp],esp 689 | mov esp,eax 690 | mov ecx,[ebp-64] 691 | mov edx,0 692 | mov dl,[ecx] 693 | sub ecx,edx 694 | mov ebx,1 695 | mov eax,4 696 | int 128 697 | push -1 698 | mov eax,[@s_esp] 699 | mov [@s_esp],esp 700 | mov esp,eax 701 | mov ebx,[ebp+12] 702 | mov eax,0 703 | mov al,[ebx] 704 | sub esp,1 705 | mov [esp],al 706 | mov [ebp-68],esp 707 | cmp eax,0 708 | je @lab_cpystr2_exit_91 709 | mov ecx,0 710 | mov esi,ebx 711 | dec esi 712 | neg eax 713 | @lab_cpystr2_90: 714 | cmp ecx,eax 715 | je @lab_cpystr2_exit_91 716 | mov dl,[esi+ecx] 717 | sub esp,1 718 | mov [esp],dl 719 | dec ecx 720 | jmp @lab_cpystr2_90 721 | @lab_cpystr2_exit_91: 722 | mov eax,[@s_esp] 723 | mov [@s_esp],esp 724 | mov esp,eax 725 | push -1 726 | mov eax,[@s_esp] 727 | mov [@s_esp],esp 728 | mov esp,eax 729 | mov ebx,[ebp+8] 730 | mov eax,0 731 | mov al,[ebx] 732 | sub esp,1 733 | mov [esp],al 734 | mov [ebp-72],esp 735 | cmp eax,0 736 | je @lab_cpystr2_exit_96 737 | mov ecx,0 738 | mov esi,ebx 739 | dec esi 740 | neg eax 741 | @lab_cpystr2_95: 742 | cmp ecx,eax 743 | je @lab_cpystr2_exit_96 744 | mov dl,[esi+ecx] 745 | sub esp,1 746 | mov [esp],dl 747 | dec ecx 748 | jmp @lab_cpystr2_95 749 | @lab_cpystr2_exit_96: 750 | mov eax,[@s_esp] 751 | mov [@s_esp],esp 752 | mov esp,eax 753 | push -1 754 | mov eax,[@s_esp] 755 | mov [@s_esp],esp 756 | mov esp,eax 757 | mov ebx,[ebp+16] 758 | mov eax,0 759 | mov al,[ebx] 760 | sub esp,1 761 | mov [esp],al 762 | mov [ebp-76],esp 763 | cmp eax,0 764 | je @lab_cpystr2_exit_101 765 | mov ecx,0 766 | mov esi,ebx 767 | dec esi 768 | neg eax 769 | @lab_cpystr2_100: 770 | cmp ecx,eax 771 | je @lab_cpystr2_exit_101 772 | mov dl,[esi+ecx] 773 | sub esp,1 774 | mov [esp],dl 775 | dec ecx 776 | jmp @lab_cpystr2_100 777 | @lab_cpystr2_exit_101: 778 | mov eax,[@s_esp] 779 | mov [@s_esp],esp 780 | mov esp,eax 781 | push 1 782 | push 0 783 | mov eax,[ebp+20] 784 | mov ebx,[ebp-80] 785 | sub eax,ebx 786 | mov [ebp-84],eax 787 | mov eax,[ebp-84] 788 | push eax 789 | mov eax,[ebp-76] 790 | push eax 791 | mov eax,[ebp-72] 792 | push eax 793 | mov eax,[ebp-68] 794 | push eax 795 | call hanoi 796 | add esp,16 797 | mov esp,ebp 798 | @if_1_end: 799 | mov ebx,[@s_ebp] 800 | mov [@s_esp],ebx 801 | mov ebx,[@s_esp] 802 | mov [@s_esp],esp 803 | mov esp,ebx 804 | pop ebx 805 | mov [@s_ebp],ebx 806 | mov ebx,[@s_esp] 807 | mov [@s_esp],esp 808 | mov esp,ebx 809 | mov esp,ebp 810 | pop ebp 811 | ret 812 | section .data 813 | @str_1 db "输入盘子个数:" 814 | @str_1_len equ 21 815 | @str_2 db "A" 816 | @str_2_len equ 1 817 | @str_3 db "B" 818 | @str_3_len equ 1 819 | @str_4 db "C" 820 | @str_4_len equ 1 821 | @str_5 db "Move " 822 | @str_5_len equ 5 823 | @str_6 db ":",9,"[" 824 | @str_6_len equ 3 825 | @str_7 db " --> " 826 | @str_7_len equ 5 827 | @str_8 db "]",10 828 | @str_8_len equ 2 829 | section .bss 830 | -------------------------------------------------------------------------------- /Compiler/compiler_test/test8.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * test case 8 3 | * recursive test [right] 4 | * right 5 | */ 6 | void hanoi(string a, string b, string c, int n); 7 | 8 | int main() { 9 | int n; 10 | out << "input number:"; 11 | in >> n; 12 | hanoi("A", "B", "C", n); 13 | return 0; 14 | } 15 | 16 | void hanoi(string a, string b, string c, int n) { 17 | if(n == 0) { 18 | return; 19 | } else { 20 | hanoi(a, c, b, n - 1); 21 | out << "Move " + n + ":\t[" + a + " --> " + c + "]\n"; 22 | hanoi(b, a, c, n - 1); 23 | } 24 | } -------------------------------------------------------------------------------- /Compiler/compiler_test/test9.s: -------------------------------------------------------------------------------- 1 | section .text 2 | main: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 0 15 | push 1 16 | section .bss 17 | -------------------------------------------------------------------------------- /Compiler/compiler_test/test9.tc: -------------------------------------------------------------------------------- 1 | /* 2 | * test case 9 3 | * semantic error 4 | * type assign error 5 | */ 6 | 7 | int main(){ 8 | int a; 9 | a = "error string!"; 10 | out << a; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Compiler/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Parser.h" 4 | #include "Generator.h" 5 | 6 | 7 | using namespace std; 8 | 9 | inline void Usage() { 10 | xSUCC("%s", "Usage:jcc src_file1 file2 ...\n"); 11 | } 12 | 13 | int main(int argc,char*argv[]) { 14 | if (argc < 2) { 15 | Usage(); 16 | } 17 | else if (strcmpi(argv[1], "jcc") == 0) { 18 | for (int i = 2; i < argc; i++) { 19 | Parser parser; 20 | parser.Init(argv[i]); 21 | parser.Program(); 22 | parser.end(); 23 | } 24 | } 25 | else { 26 | xWARN("%s%s%s", "Not recognize command ", argv[1], " ,using jcc \n"); 27 | Usage(); 28 | } 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /Compiler/make.bat: -------------------------------------------------------------------------------- 1 | ..\make_tool\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 -------------------------------------------------------------------------------- /Linker/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | #define SYM_SEG ".symtab" 7 | #define STR_SEG ".strtab" 8 | #define REL_SEG ".rel" 9 | #define START "_start" 10 | #define TEXT_SEG ".text" 11 | #define DATA_SEG ".data" 12 | #define BSS_SEG ".bss" 13 | #define SH_STR_SEG ".shstrtab" 14 | 15 | 16 | #define BASE_ADDR 0x08040000 17 | #define MEM_ALIGN 0x1000 18 | #define DISC_ALIGN 4 19 | #define TEXT_ALIGN 16 20 | 21 | 22 | // 23 | // aux routines for colorful printf. And you should not pay more attention to them 24 | // 25 | #define xINFO(_X_,...) color_printf(FG_WHITE,_X_,__VA_ARGS__) 26 | 27 | #define xPANIC(_X_,...) color_printf(FG_RED,_X_,__VA_ARGS__) 28 | 29 | #define xSUCC(_X_,...) color_printf(FG_GREEN,_X_,__VA_ARGS__) 30 | 31 | #define xWARN(_X_,...) color_printf(FG_YELLOW,_X_,__VA_ARGS__) 32 | 33 | 34 | #define FG_BLACK 0x00 35 | #define FG_BLUE 0x01 36 | #define FG_GREEN 0x02 37 | #define FG_BLUE_2 0x03 38 | #define FG_RED 0x04 39 | #define FG_PURPLE 0x05 40 | #define FG_YELLOW 0x06 41 | #define FG_WHITE 0x0F 42 | 43 | inline void setColor(int color, const bool bIntensity = true) { 44 | SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color | (bIntensity ? FOREGROUND_INTENSITY : 0)); 45 | } 46 | 47 | inline void resetColor() { 48 | setColor(FG_WHITE); 49 | } 50 | 51 | inline int color_printf(const int color, const char* pszFmt, ...) { 52 | if (color != -1) { 53 | setColor(color); 54 | } 55 | va_list marker; 56 | va_start(marker, pszFmt); 57 | auto ri = vprintf(pszFmt, marker); 58 | va_end(marker); 59 | resetColor(); 60 | return ri; 61 | } 62 | -------------------------------------------------------------------------------- /Linker/Elf_File.cpp: -------------------------------------------------------------------------------- 1 | #include "Elf_File.h" 2 | #include "Common.h" 3 | 4 | 5 | RelItem::RelItem() { 6 | this->rel = nullptr; 7 | this->seg_name = ""; 8 | this->rel_name = ""; 9 | } 10 | 11 | RelItem::RelItem(string seg_name, Elf32_Rel* r, string rel_name) { 12 | this->seg_name = seg_name; 13 | this->rel = r; 14 | this->rel_name = rel_name; 15 | } 16 | 17 | RelItem::~RelItem() { 18 | delete rel; 19 | } 20 | 21 | string RelItem::get_rel_name() { 22 | return rel_name; 23 | } 24 | 25 | string RelItem::get_seg_name() { 26 | return seg_name; 27 | } 28 | 29 | 30 | Elf_File::Elf_File() { 31 | this->ehdr = Elf32_Ehdr(); 32 | this->file_name = ""; 33 | this->str_tab = nullptr; 34 | this->shstr_tab = nullptr; 35 | this->shstr_tab_size = 0; 36 | this->str_tab_size = 0; 37 | this->phdr_tab.clear(); 38 | this->shdr_tab.clear(); 39 | this->shdr_names.clear(); 40 | this->sym_names.clear(); 41 | this->rel_tab.clear(); 42 | this->sym_tab.clear(); 43 | } 44 | 45 | void Elf_File::ReadElf(const char* file_name) { 46 | this->file_name = file_name; 47 | FILE* fp = fopen(file_name, "rb"); 48 | if (fp != nullptr) { 49 | rewind(fp); 50 | fread(&ehdr, sizeof(Elf32_Ehdr), 1,fp); 51 | // excutive file 52 | if (ehdr.e_type == ET_EXEC) { 53 | fseek(fp, ehdr.e_phoff, 0); 54 | for (int i = 0; i < ehdr.e_phnum; i++) { 55 | Elf32_Phdr* phdr = new Elf32_Phdr(); 56 | fread(phdr, sizeof(Elf32_Phdr), 1, fp); 57 | phdr_tab.push_back(phdr); 58 | } 59 | } 60 | 61 | // shstrtab 62 | fseek(fp, ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shstrndx, 0); 63 | Elf32_Shdr shstr_tab; 64 | fread(&shstr_tab, sizeof(Elf32_Shdr), 1, fp); 65 | char* shstr_tab_data = new char[shstr_tab.sh_size]; 66 | fseek(fp, shstr_tab.sh_offset, 0); 67 | fread(shstr_tab_data, shstr_tab.sh_size, 1, fp); 68 | 69 | // shdr 70 | fseek(fp, ehdr.e_shoff, 0); 71 | for (int i = 0; i < ehdr.e_shnum; i++) { 72 | Elf32_Shdr* shdr = new Elf32_Shdr(); 73 | fread(shdr, ehdr.e_shentsize, 1, fp); 74 | string tmp_name(shstr_tab_data + shdr->sh_name); 75 | shdr_names.push_back(tmp_name); 76 | if (tmp_name.empty()) { 77 | delete shdr; 78 | } 79 | else { 80 | shdr_tab[tmp_name] = shdr; 81 | } 82 | } 83 | delete[] shstr_tab_data; 84 | 85 | // strtab 86 | Elf32_Shdr* strtab = shdr_tab[STR_SEG]; 87 | char* str_tab_data = new char[strtab->sh_size]; 88 | fseek(fp, strtab->sh_offset, 0); 89 | fread(str_tab_data, strtab->sh_size, 1, fp); 90 | 91 | // symtab 92 | Elf32_Shdr* sh_symtab = shdr_tab[SYM_SEG]; 93 | fseek(fp, sh_symtab->sh_offset, 0); 94 | int sym_number = sh_symtab->sh_size / (sizeof(Elf32_Sym)); 95 | vectorsym_list; 96 | for (int i = 0; i < sym_number; i++) { 97 | Elf32_Sym* sym_tmp = new Elf32_Sym(); 98 | fread(sym_tmp, sizeof(Elf32_Sym), 1, fp); 99 | sym_list.push_back(sym_tmp); 100 | string tmp_name(str_tab_data + sym_tmp->st_name); 101 | if (tmp_name.empty()) { 102 | delete sym_tmp; 103 | } 104 | else { 105 | sym_tab[tmp_name] = sym_tmp; 106 | } 107 | } 108 | 109 | // reltab 110 | unordered_map::iterator i; 111 | for (i = shdr_tab.begin(); i != shdr_tab.end(); i++) { 112 | if (i->first.find(REL_SEG) == 0) { 113 | Elf32_Shdr* shrel_tab = shdr_tab[i->first]; 114 | fseek(fp, shrel_tab->sh_offset, 0); 115 | int rel_number = shrel_tab->sh_size / sizeof(Elf32_Rel); 116 | for (int k = 0; k < rel_number; k++) { 117 | Elf32_Rel* r = new Elf32_Rel(); 118 | fread(r, sizeof(Elf32_Rel), 1, fp); 119 | string tmp_name(str_tab_data + sym_list[ELF32_R_SYM(r->r_info)]->st_name); 120 | rel_tab.push_back(new RelItem(i->first.substr(4), r, tmp_name)); 121 | } 122 | } 123 | } 124 | 125 | delete[] str_tab_data; 126 | fclose(fp); 127 | fp = nullptr; 128 | } 129 | else { 130 | xPANIC("%s%s%s", "file ", file_name, " not exit!\n"); 131 | exit(0); 132 | } 133 | } 134 | 135 | void Elf_File::GetData(char* buffer, Elf32_Off offset, Elf32_Word size) { 136 | FILE* fp = fopen(file_name.c_str(), "rb"); 137 | if (fp != nullptr) { 138 | rewind(fp); 139 | fseek(fp, offset, 0); 140 | fread(buffer, size, 1, fp); 141 | fclose(fp); 142 | fp = nullptr; 143 | } 144 | else { 145 | xPANIC("%s%s%s", "file ", file_name, " not exit!\n"); 146 | exit(0); 147 | } 148 | } 149 | 150 | int Elf_File::GetSegIndex(string seg_name) { 151 | int index = 0; 152 | for (int i = 0; i < shdr_names.size(); i++) { 153 | if (seg_name == shdr_names[i]) { 154 | break; 155 | } 156 | index++; 157 | } 158 | return index; 159 | } 160 | 161 | int Elf_File::GetSymIndex(string sym_name) { 162 | int index = 0; 163 | for (int i = 0; i < sym_names.size(); i++) { 164 | if (sym_name == shdr_names[i]) { 165 | break; 166 | } 167 | index++; 168 | } 169 | return index; 170 | } 171 | 172 | void Elf_File::AddPhdr(Elf32_Word type, Elf32_Off offset, Elf32_Addr vir_addr, 173 | Elf32_Word file_size, Elf32_Word mem_size, 174 | Elf32_Word flags, Elf32_Word align) { 175 | Elf32_Phdr* ph = new Elf32_Phdr(); 176 | ph->p_type = type; 177 | ph->p_offset = offset; 178 | ph->p_vaddr = vir_addr; 179 | ph->p_paddr = vir_addr; 180 | ph->p_filesz = file_size; 181 | ph->p_memsz = mem_size; 182 | ph->p_flags = flags; 183 | ph->p_align = align; 184 | phdr_tab.push_back(ph); 185 | } 186 | 187 | void Elf_File::AddShdr(string sh_name, Elf32_Word sh_type, Elf32_Word sh_flags, 188 | Elf32_Addr sh_addr, Elf32_Off sh_offset, Elf32_Word sh_size, 189 | Elf32_Word sh_link,Elf32_Word sh_info, Elf32_Word sh_align, 190 | Elf32_Word sh_entsize) { 191 | Elf32_Shdr* sh = new Elf32_Shdr(); 192 | sh->sh_name = 0; 193 | sh->sh_type = sh_type; 194 | sh->sh_flags = sh_flags; 195 | sh->sh_addr = sh_addr; 196 | sh->sh_offset = sh_offset; 197 | sh->sh_size = sh_size; 198 | sh->sh_link = sh_link; 199 | sh->sh_info = sh_info; 200 | sh->sh_addralign = sh_align; 201 | sh->sh_entsize = sh_entsize; 202 | shdr_tab[sh_name] = sh; 203 | shdr_names.push_back(sh_name); 204 | } 205 | 206 | 207 | void Elf_File::AddSym(string name, Elf32_Sym* s) { 208 | sym_tab[name] = new Elf32_Sym(); 209 | Elf32_Sym* sym = sym_tab[name]; 210 | if (name == "") { 211 | sym->st_name = 0; 212 | sym->st_value = 0; 213 | sym->st_size = 0; 214 | sym->st_info = 0; 215 | sym->st_other = 0; 216 | sym->st_shndx = 0; 217 | } 218 | else { 219 | sym->st_name = 0; 220 | sym->st_value = s->st_value; 221 | sym->st_size = s->st_size; 222 | sym->st_info = s->st_info; 223 | sym->st_other = s->st_other; 224 | sym->st_shndx = s->st_shndx; 225 | } 226 | sym_names.push_back(name); 227 | } 228 | 229 | void Elf_File::Write(const char* output, bool flag) { 230 | if (flag) { 231 | FILE* fp = fopen(output, "wb"); 232 | fwrite(&ehdr, ehdr.e_ehsize, 1, fp); 233 | fflush(fp); 234 | if (!phdr_tab.empty()) { 235 | for (int i = 0; i < phdr_tab.size(); i++) { 236 | fwrite(phdr_tab[i], sizeof(Elf32_Phdr), 1, fp); 237 | fflush(fp); 238 | } 239 | } 240 | fclose(fp); 241 | fp = nullptr; 242 | } 243 | else { 244 | FILE* fp = fopen(output,"ab"); 245 | fwrite(shstr_tab, shstr_tab_size, 1, fp); 246 | fflush(fp); 247 | 248 | for (int i = 0; i < shdr_names.size(); i++) { 249 | Elf32_Shdr* sh = shdr_tab[shdr_names[i]]; 250 | fwrite(sh, sizeof(Elf32_Shdr), 1, fp); 251 | fflush(fp); 252 | } 253 | 254 | for (int i = 0; i < sym_names.size(); i++) { 255 | Elf32_Sym* s = sym_tab[sym_names[i]]; 256 | fwrite(s, sizeof(Elf32_Sym), 1, fp); 257 | fflush(fp); 258 | } 259 | 260 | fwrite(str_tab, str_tab_size, 1, fp); 261 | fflush(fp); 262 | fclose(fp); 263 | fp = nullptr; 264 | } 265 | } -------------------------------------------------------------------------------- /Linker/Elf_File.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "elf.h" 7 | 8 | 9 | using namespace std; 10 | 11 | class RelItem { 12 | private: 13 | string seg_name; 14 | string rel_name; 15 | public: 16 | Elf32_Rel* rel; 17 | public: 18 | RelItem(); 19 | RelItem(string seg_name, Elf32_Rel* r, string rel_name); 20 | ~RelItem(); 21 | // default API 22 | string get_seg_name(); 23 | string get_rel_name(); 24 | }; 25 | 26 | 27 | class Elf_File 28 | { 29 | public: 30 | Elf32_Ehdr ehdr; 31 | vectorphdr_tab; 32 | unordered_mapshdr_tab; 33 | vectorshdr_names; 34 | unordered_mapsym_tab; 35 | vectorsym_names; 36 | vectorrel_tab; 37 | string file_name; 38 | char* shstr_tab; 39 | int shstr_tab_size; 40 | char* str_tab; 41 | int str_tab_size; 42 | public: 43 | Elf_File(); 44 | void ReadElf(const char* file_name); 45 | void GetData(char*buffer,Elf32_Off offset,Elf32_Word size); 46 | int GetSegIndex(string seg_name); 47 | int GetSymIndex(string sym_name); 48 | void AddPhdr(Elf32_Word type, Elf32_Off offset, Elf32_Addr vir_addr, 49 | Elf32_Word file_size, Elf32_Word mem_size, Elf32_Word flags, Elf32_Word align); 50 | void AddShdr(string sh_name, Elf32_Word sh_type, Elf32_Word sh_flags, 51 | Elf32_Addr sh_addr, Elf32_Off sh_offset, Elf32_Word sh_size, Elf32_Word sh_link, 52 | Elf32_Word sh_info, Elf32_Word sh_align, Elf32_Word sh_entsize); 53 | 54 | void AddSym(string name, Elf32_Sym* s); 55 | void Write(const char* output, bool flag); 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /Linker/Link.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string.h" 3 | #include "elf.h" 4 | #include "Link.h" 5 | #include "Common.h" 6 | 7 | 8 | 9 | using namespace std; 10 | 11 | Block::Block(char* data, int offset, int size) { 12 | this->data = data; 13 | this->offset = offset; 14 | this->block_size = size; 15 | } 16 | 17 | Block::~Block() { 18 | if (data) { 19 | delete[] data; 20 | data = nullptr; 21 | } 22 | } 23 | 24 | int Block::get_offset() { 25 | return this->offset; 26 | } 27 | 28 | int Block::get_block_size() { 29 | return this->block_size; 30 | } 31 | 32 | char* Block::get_data() { 33 | return data; 34 | } 35 | 36 | SegList::SegList() { 37 | this->begin = 0; 38 | this->base_addr = 0; 39 | this->offset = 0; 40 | this->size = 0; 41 | this->blocks.clear(); 42 | this->file_list.clear(); 43 | } 44 | 45 | SegList::~SegList() { 46 | file_list.clear(); 47 | file_list.shrink_to_fit(); 48 | for (int i = 0; i < blocks.size(); i++) { 49 | delete blocks[i]; 50 | } 51 | blocks.clear(); 52 | blocks.shrink_to_fit(); 53 | } 54 | 55 | void SegList::AllocAddr(string name, int& base, int& offset) { 56 | begin = offset; 57 | if (name != BSS_SEG) 58 | base += (MEM_ALIGN - base % MEM_ALIGN) % MEM_ALIGN; 59 | int align = DISC_ALIGN; 60 | if (name == TEXT_SEG) { 61 | align = TEXT_ALIGN; 62 | } 63 | offset += (align - offset % align) % align; 64 | base = base - base % MEM_ALIGN + offset % MEM_ALIGN; 65 | this->base_addr = base; 66 | this->offset = offset; 67 | this->size = 0; 68 | for (int i = 0; i < file_list.size(); i++) { 69 | size += (DISC_ALIGN - size % DISC_ALIGN) % DISC_ALIGN; 70 | Elf32_Shdr* seg = file_list[i]->shdr_tab[name]; 71 | if (name != BSS_SEG) { 72 | char* buffer = new char[seg->sh_size]; 73 | file_list[i]->GetData(buffer, seg->sh_offset, seg->sh_size); 74 | blocks.push_back(new Block(buffer, size, seg->sh_size)); 75 | } 76 | seg->sh_addr = base + size; 77 | size += seg->sh_size; 78 | } 79 | base += size; 80 | if (name != BSS_SEG) { 81 | offset += size; 82 | } 83 | } 84 | 85 | void SegList::RelocAddr(int rel_addr, int type, int sym_addr) { 86 | int rel_offset = rel_addr - base_addr; 87 | Block* block = nullptr; 88 | for (int i = 0; i < blocks.size(); i++) { 89 | if (blocks[i]->get_offset() <= rel_offset && 90 | blocks[i]->get_offset() + blocks[i]->get_block_size() > rel_offset) { 91 | block = blocks[i]; 92 | break; 93 | } 94 | } 95 | 96 | if (block) { 97 | int* addr = (int*)(block->get_data() + rel_offset - block->get_offset()); 98 | if (type == R_386_32) { 99 | *addr = sym_addr; 100 | 101 | } 102 | else if (type == R_386_PC32) { 103 | *addr = sym_addr - rel_addr + *addr; 104 | } 105 | } 106 | } 107 | 108 | int SegList::get_base_addr() { 109 | return base_addr; 110 | } 111 | 112 | int SegList::get_offset() { 113 | return offset; 114 | } 115 | 116 | int SegList::get_size() { 117 | return size; 118 | } 119 | 120 | int SegList::get_begin() { 121 | return begin; 122 | } 123 | 124 | Link::Link() { 125 | this->start = nullptr; 126 | this->files.clear(); 127 | this->all_sym.clear(); 128 | this->sym_def.clear(); 129 | this->seg_name.clear(); 130 | this->seg_list.clear(); 131 | seg_name.push_back(TEXT_SEG); 132 | seg_name.push_back(DATA_SEG); 133 | seg_name.push_back(BSS_SEG); 134 | for (int i = 0; i < seg_name.size(); i++) { 135 | seg_list[seg_name[i]] = new SegList(); 136 | } 137 | } 138 | 139 | void Link::AddElf(const char* file_name) { 140 | Elf_File* elf = new Elf_File(); 141 | elf->ReadElf(file_name); 142 | files.push_back(elf); 143 | } 144 | 145 | void Link::CollectInfo() { 146 | for (int i = 0; i < files.size(); i++) { 147 | Elf_File* elf = files[i]; 148 | for (int i = 0; i < seg_name.size(); i++) { 149 | if (elf->shdr_tab.find(seg_name[i]) != elf->shdr_tab.end()) { 150 | seg_list[seg_name[i]]->file_list.push_back(elf); 151 | } 152 | } 153 | 154 | unordered_map::iterator it; 155 | for (it = elf->sym_tab.begin(); it != elf->sym_tab.end(); it++) { 156 | SymLink* slink = new SymLink(); 157 | slink->name = it->first; 158 | if (it->second->st_shndx == STN_UNDEF) { 159 | slink->recv = elf; 160 | slink->prov = nullptr; 161 | all_sym.push_back(slink); 162 | } 163 | else { 164 | slink->prov = elf; 165 | slink->recv = nullptr; 166 | sym_def.push_back(slink); 167 | } 168 | } 169 | } 170 | } 171 | 172 | bool Link::CheckSymIsValid() { 173 | bool res_flag = true; 174 | start = nullptr; 175 | for (int i = 0; i < sym_def.size(); i++) { 176 | if (ELF32_ST_BIND(sym_def[i]->prov->sym_tab[sym_def[i]->name]->st_info) 177 | != STB_GLOBAL) 178 | continue; 179 | if (sym_def[i]->name == START) { 180 | start = sym_def[i]->prov; 181 | } 182 | for (int k = i + 1; k < sym_def.size(); k++) { 183 | if (ELF32_ST_BIND(sym_def[k]->prov->sym_tab[sym_def[k]->name]->st_info) 184 | != STB_GLOBAL) 185 | continue; 186 | if (sym_def[i]->name == sym_def[k]->name) { 187 | // error 188 | xPANIC("%s", "Link error:\n"); 189 | xWARN("%s%s%s%s%s%s%s", "symname [", (sym_def[i]->name).c_str(), 190 | "] in file <", (sym_def[i]->prov->file_name).c_str() 191 | , "> conflict with file <", 192 | sym_def[k]->prov->file_name, ">\n"); 193 | res_flag = false; 194 | } 195 | } 196 | 197 | } 198 | if (start == nullptr) { 199 | // error 200 | xPANIC("%s\n", "Link error:"); 201 | xWARN("%s\n", "Can't find excutive entry!"); 202 | res_flag = false; 203 | } 204 | for (int i = 0; i < all_sym.size(); i++) { 205 | for (int k = 0; k < sym_def.size(); k++) { 206 | if (ELF32_ST_BIND(sym_def[k]->prov->sym_tab[sym_def[k]->name]->st_info) 207 | != STB_GLOBAL) 208 | continue; 209 | if (sym_def[k]->name == all_sym[i]->name) { 210 | all_sym[i]->prov = sym_def[k]->prov; 211 | sym_def[k]->recv = sym_def[k]->prov; 212 | } 213 | } 214 | if (all_sym[i]->prov == nullptr) { 215 | // error 216 | xPANIC("%s\n", "Link error:"); 217 | int info = all_sym[i]->recv->sym_tab[all_sym[i]->name]->st_info; 218 | string type = ""; 219 | if (ELF32_ST_TYPE(info) == STT_OBJECT) type = "variable"; 220 | else if (ELF32_ST_TYPE(info) == STT_FUNC) type = "func"; 221 | else type = "symbol"; 222 | xWARN("%s%s%s%s%s%s", type.c_str(), " [", 223 | (all_sym[i]->name).c_str(), "] is not defined in file <" 224 | , (all_sym[i]->recv->file_name).c_str(), ">\n"); 225 | 226 | res_flag = false; 227 | } 228 | } 229 | return res_flag; 230 | } 231 | 232 | void Link::AllocAddr() { 233 | int cur_addr = BASE_ADDR; 234 | int cur_offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * seg_name.size(); 235 | 236 | for (int i = 0; i < seg_name.size(); i++) { 237 | seg_list[seg_name[i]]->AllocAddr(seg_name[i], cur_addr, cur_offset); 238 | } 239 | } 240 | 241 | void Link::SymParser() { 242 | for (int i = 0; i < sym_def.size(); i++) { 243 | Elf32_Sym* s = sym_def[i]->prov->sym_tab[sym_def[i]->name]; 244 | string seg_name = sym_def[i]->prov->shdr_names[s->st_shndx]; 245 | s->st_value += sym_def[i]->prov->shdr_tab[seg_name]->sh_addr; 246 | } 247 | 248 | for (int i = 0; i < all_sym.size(); i++) { 249 | Elf32_Sym* s_pro = all_sym[i]->prov->sym_tab[all_sym[i]->name]; 250 | Elf32_Sym* s_rev = all_sym[i]->recv->sym_tab[all_sym[i]->name]; 251 | s_rev->st_value = s_pro->st_value; 252 | } 253 | } 254 | 255 | void Link::Relocation() { 256 | for (int i = 0; i < files.size(); i++) { 257 | vectorrel_tabs = files[i]->rel_tab; 258 | for (int k = 0; k < rel_tabs.size(); k++) { 259 | Elf32_Sym* s = files[i]->sym_tab[rel_tabs[k]->get_rel_name()]; 260 | int sym_addr = s->st_value; 261 | int rel_addr = files[i]->shdr_tab[rel_tabs[k]->get_seg_name()]->sh_addr + 262 | rel_tabs[k]->rel->r_offset; 263 | seg_list[rel_tabs[k]->get_seg_name()]->RelocAddr(rel_addr, 264 | ELF32_R_TYPE(rel_tabs[k]->rel->r_info), sym_addr); 265 | } 266 | } 267 | } 268 | 269 | void Link::AssemblyObj() { 270 | int* pointer = (int*)obj.ehdr.e_ident; 271 | *pointer = 0x464c457f; 272 | pointer++; 273 | *pointer = 0x00010101; 274 | pointer++; 275 | *pointer = 0x00; 276 | pointer++; 277 | *pointer = 0x00; 278 | obj.ehdr.e_type = ET_EXEC; 279 | obj.ehdr.e_machine = EM_386; 280 | obj.ehdr.e_version = EV_CURRENT; 281 | obj.ehdr.e_flags = 0; 282 | obj.ehdr.e_ehsize = 52; 283 | int cur_offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * seg_name.size(); 284 | obj.AddShdr("", 0, 0, 0, 0, 0, 0, 0, 0, 0); 285 | int shstr_tab_size = 26; 286 | /* SH_STR_SEG + SYM_SEG + STR_SRG + 3 */ 287 | for (int i = 0; i < seg_name.size(); i++) { 288 | string name = seg_name[i]; 289 | shstr_tab_size += (name.size() + 1); 290 | Elf32_Word flags = PF_W | PF_R; 291 | Elf32_Word filesz = seg_list[name]->get_size(); 292 | if (name == TEXT_SEG) flags = PF_X | PF_R; 293 | if (name == BSS_SEG) filesz = 0; 294 | obj.AddPhdr(PT_LOAD, seg_list[name]->get_offset(), seg_list[name]->get_base_addr(), 295 | filesz, seg_list[name]->get_size(), flags, MEM_ALIGN); 296 | cur_offset = seg_list[name]->get_offset(); 297 | 298 | 299 | Elf32_Word sh_type = SHT_PROGBITS; 300 | Elf32_Word sh_flags = SHF_ALLOC | SHF_WRITE; 301 | Elf32_Word sh_align = DISC_ALIGN; 302 | if (name == BSS_SEG) sh_type = SHT_NOBITS; 303 | if (name == TEXT_SEG) { 304 | sh_flags = SHF_ALLOC | SHF_EXECINSTR; 305 | sh_align = TEXT_ALIGN; 306 | } 307 | obj.AddShdr(name, sh_type, sh_flags, seg_list[name]->get_base_addr(), 308 | seg_list[name]->get_offset(), seg_list[name]->get_size(), SHN_UNDEF, 0, sh_align, 0); 309 | } 310 | obj.ehdr.e_phoff = sizeof(Elf32_Ehdr); 311 | obj.ehdr.e_phentsize = sizeof(Elf32_Phdr); 312 | obj.ehdr.e_phnum = seg_name.size(); 313 | 314 | // shstrtab 315 | obj.shstr_tab = new char[shstr_tab_size]; 316 | char* str = obj.shstr_tab; 317 | obj.shstr_tab_size = shstr_tab_size; 318 | int index = 0; 319 | unordered_mapshstr_index; 320 | shstr_index.clear(); 321 | 322 | shstr_index[SH_STR_SEG] = index; 323 | strcpy(str + index, SH_STR_SEG); 324 | index += 10; 325 | 326 | shstr_index[SYM_SEG] = index; 327 | strcpy(str + index, SYM_SEG); 328 | index += 8; 329 | 330 | shstr_index[STR_SEG] = index; 331 | strcpy(str + index, STR_SEG); 332 | index += 8; 333 | 334 | shstr_index[""] = index - 1; 335 | 336 | for (int i = 0; i < seg_name.size(); i++) { 337 | shstr_index[seg_name[i]] = index; 338 | strcpy(str + index, seg_name[i].c_str()); 339 | index += seg_name[i].size() + 1; 340 | } 341 | 342 | obj.AddShdr(SH_STR_SEG, SHT_STRTAB, 0, 0, cur_offset, shstr_tab_size, SHN_UNDEF, 0, 1, 0); 343 | obj.ehdr.e_shstrndx = obj.GetSegIndex(SH_STR_SEG); 344 | 345 | cur_offset += shstr_tab_size; 346 | 347 | obj.ehdr.e_shoff = cur_offset; 348 | obj.ehdr.e_shentsize = sizeof(Elf32_Shdr); 349 | obj.ehdr.e_shnum = 4 + seg_name.size(); 350 | cur_offset += sizeof(Elf32_Shdr) * (obj.ehdr.e_shnum); 351 | 352 | obj.AddShdr(SYM_SEG, SHT_SYMTAB, 0, 0, cur_offset, 353 | (1 + sym_def.size()) * sizeof(Elf32_Sym), 0, 0, 1, sizeof(Elf32_Sym)); 354 | obj.shdr_tab[SYM_SEG]->sh_link = obj.GetSegIndex(SYM_SEG) + 1; 355 | 356 | int str_tab_size = 0; 357 | obj.AddSym("", nullptr); 358 | for (int i = 0; i < sym_def.size(); i++) { 359 | string name = sym_def[i]->name; 360 | str_tab_size += name.size() + 1; 361 | Elf32_Sym* s = sym_def[i]->prov->sym_tab[name]; 362 | s->st_shndx = obj.GetSegIndex(sym_def[i]->prov->shdr_names[s->st_shndx]); 363 | obj.AddSym(name, s); 364 | } 365 | 366 | obj.ehdr.e_entry = obj.sym_tab[START]->st_value; 367 | cur_offset += (1 + sym_def.size()) * sizeof(Elf32_Sym); 368 | obj.AddShdr(STR_SEG, SHT_STRTAB, 0, 0, cur_offset, str_tab_size, SHN_UNDEF, 0, 1, 0); 369 | 370 | obj.str_tab = new char[str_tab_size]; 371 | str = obj.str_tab; 372 | obj.str_tab_size = str_tab_size; 373 | index = 0; 374 | unordered_mapstr_index; 375 | str_index.clear(); 376 | str_index[""] = str_tab_size - 1; 377 | for (int i = 0; i < sym_def.size(); i++) { 378 | str_index[sym_def[i]->name] = index; 379 | strcpy(str + index, sym_def[i]->name.c_str()); 380 | index += sym_def[i]->name.size() + 1; 381 | } 382 | 383 | unordered_map::iterator it; 384 | for (it = obj.sym_tab.begin(); it != obj.sym_tab.end(); it++) { 385 | it->second->st_name = str_index[it->first]; 386 | } 387 | 388 | unordered_map::iterator is; 389 | for (is = obj.shdr_tab.begin(); is != obj.shdr_tab.end(); is++) { 390 | is->second->sh_name = shstr_index[is->first]; 391 | } 392 | } 393 | 394 | void Link::ExportElf(const char* file_name) { 395 | obj.Write(file_name, true); 396 | FILE* fp = fopen(file_name, "ab"); 397 | char pading = 0; 398 | for (int i = 0; i < seg_name.size(); i++) { 399 | SegList* sl = seg_list[seg_name[i]]; 400 | int padding_number = sl->get_offset() - sl->get_begin(); 401 | while (padding_number--) { 402 | fwrite(&pading, 1, 1, fp); 403 | fflush(fp); 404 | } 405 | if (seg_name[i] != BSS_SEG) { 406 | Block* old_block = nullptr; 407 | char instruction_padding = 0x90; 408 | for (int k = 0; k < sl->blocks.size(); k++) { 409 | Block* new_block = sl->blocks[k]; 410 | if (old_block != nullptr) { 411 | padding_number = new_block->get_offset() - 412 | (old_block->get_offset() + 413 | old_block->get_block_size()); 414 | while (padding_number--) { 415 | fwrite(&instruction_padding, 1, 1, fp); 416 | fflush(fp); 417 | } 418 | } 419 | old_block = new_block; 420 | fwrite(new_block->get_data(), new_block->get_block_size(), 1, fp); 421 | fflush(fp); 422 | } 423 | } 424 | } 425 | fclose(fp); 426 | fp = nullptr; 427 | obj.Write(file_name, false); 428 | return; 429 | } 430 | 431 | bool Link::Excute(const char*file_name) { 432 | CollectInfo(); 433 | if (!CheckSymIsValid()) { 434 | xPANIC("%s", "Linking failed!\n"); 435 | return false; 436 | } 437 | AllocAddr(); 438 | SymParser(); 439 | Relocation(); 440 | AssemblyObj(); 441 | ExportElf(file_name); 442 | xSUCC("%s", "Linking successfully!\n"); 443 | xSUCC("%s%s\n", "output file >>> ", file_name); 444 | return true; 445 | } 446 | 447 | Link::~Link() { 448 | unordered_map::iterator it; 449 | it = seg_list.begin(); 450 | for (it; it != seg_list.end(); it++) { 451 | delete it->second; 452 | } 453 | seg_list.clear(); 454 | 455 | for (int i = 0; i < sym_def.size(); i++) { 456 | delete sym_def[i]; 457 | } 458 | sym_def.clear(); 459 | sym_def.shrink_to_fit(); 460 | 461 | for (int i = 0; i < all_sym.size(); i++) { 462 | delete all_sym[i]; 463 | } 464 | all_sym.clear(); 465 | all_sym.shrink_to_fit(); 466 | 467 | for (int i = 0; i < files.size(); i++) { 468 | delete files[i]; 469 | } 470 | files.clear(); 471 | files.shrink_to_fit(); 472 | } -------------------------------------------------------------------------------- /Linker/Link.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Elf_File.h" 7 | 8 | 9 | using namespace std; 10 | class Block { 11 | private: 12 | char* data; 13 | int offset; 14 | int block_size; 15 | public: 16 | Block(char* data, int offset, int size); 17 | ~Block(); 18 | int get_offset(); 19 | int get_block_size(); 20 | char* get_data(); 21 | }; 22 | 23 | class SegList { 24 | private: 25 | int base_addr; 26 | int offset; 27 | int size; 28 | int begin; 29 | public: 30 | vectorfile_list; 31 | vectorblocks; 32 | public: 33 | ~SegList(); 34 | SegList(); 35 | void AllocAddr(string name, int& base, int& offset); 36 | void RelocAddr(int rel_addr, int type, int sym_addr); 37 | // default API 38 | int get_base_addr(); 39 | int get_offset(); 40 | int get_size(); 41 | int get_begin(); 42 | }; 43 | 44 | class SymLink { 45 | public: 46 | string name; 47 | Elf_File* recv; 48 | Elf_File* prov; 49 | }; 50 | 51 | 52 | class Link 53 | { 54 | private: 55 | vectorseg_name; 56 | Elf_File obj; 57 | Elf_File* start; 58 | public: 59 | vectorfiles; 60 | unordered_map seg_list; 61 | vectorall_sym; 62 | vectorsym_def; 63 | public: 64 | Link(); 65 | ~Link(); 66 | void AddElf(const char* file_name); 67 | void CollectInfo(); 68 | bool CheckSymIsValid(); 69 | void AllocAddr(); 70 | void SymParser(); 71 | void Relocation(); 72 | void AssemblyObj(); 73 | void ExportElf(const char*file_name); 74 | bool Excute(const char* file_name); 75 | }; 76 | 77 | -------------------------------------------------------------------------------- /Linker/Linker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Linker", "Linker.vcxproj", "{D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Debug|x64.ActiveCfg = Debug|x64 17 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Debug|x64.Build.0 = Debug|x64 18 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Debug|x86.ActiveCfg = Debug|Win32 19 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Debug|x86.Build.0 = Debug|Win32 20 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Release|x64.ActiveCfg = Release|x64 21 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Release|x64.Build.0 = Release|x64 22 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Release|x86.ActiveCfg = Release|Win32 23 | {D8B5EFA9-4F8C-4CB7-AE3B-A6F02C957093}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {A9889BA4-1C2E-49CC-8CD1-E1EAE0741A5B} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Linker/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # make 3 | TOOL_PATH = ../make_tool/ 4 | 5 | MAKE = $(TOOL_PATH) make.exe -r 6 | SRC = main.cpp Link.cpp Elf_File.cpp 7 | SRC_H = Common.h Link.h Elf_File.h elf.h 8 | FLAGS = -g -Wno-deprecated -std=c++11 9 | # -g 编译产生调试信息 10 | # -Wno-deprecated 忽略头文件依赖的警告 11 | # -std=c++11 使用C++11 12 | # compile 13 | link: $(SRC) $(SRC_H) Makefile 14 | g++ $(SRC) -o linker.exe $(FLAGS) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Linker/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Common.h" 3 | #include "string.h" 4 | #include "Link.h" 5 | 6 | 7 | using namespace std; 8 | 9 | void Usage() { 10 | xWARN("%s", "link obj1 obj2 ... [-o out_name]\n"); 11 | xWARN("%s", "default output name is a.out\n"); 12 | } 13 | 14 | int main(int argc, char* argv[]) { 15 | if (argc < 2) { 16 | Usage(); 17 | } 18 | else if (strcmpi(argv[1], "link") == 0) { 19 | Link linker; 20 | int i = 2; 21 | for (i; i < argc; i++) { 22 | if (strcmpi(argv[i], "-o") == 0) { 23 | i++; 24 | break; 25 | } 26 | linker.AddElf(argv[i]); 27 | } 28 | if (argc >= 3) { 29 | if (i < argc) { 30 | linker.Excute(argv[i]); 31 | } 32 | else { 33 | string prefix = argv[2]; 34 | int index = prefix.find_last_of("\\"); 35 | if (index == string::npos) { 36 | index = prefix.find_last_of("/"); 37 | } 38 | prefix = prefix.substr(0, index) + "\\a.out"; 39 | linker.Excute(prefix.c_str()); 40 | } 41 | } 42 | } 43 | else { 44 | xPANIC("%s%s%s", "Not recognize command ", argv[1], " ,using link\n"); 45 | Usage(); 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /Linker/make.bat: -------------------------------------------------------------------------------- 1 | ..\make_tool\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # make 3 | TOOL_PATH = ./make_tool/ 4 | 5 | MAKE = $(TOOL_PATH) make.exe -r 6 | SRC = main.cpp 7 | FLAGS = -g -Wno-deprecated -std=c++11 -w 8 | # -g 编译产生调试信息 9 | # -Wno-deprecated 忽略头文件依赖的警告 10 | # -std=c++11 使用C++11 11 | # -w 忽略警告 12 | # compile 13 | jcc: $(SRC) Makefile 14 | g++ $(SRC) -o jcc.exe $(FLAGS) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny-C-Compiler 2 | 简化版`C`语言编译器,编译系统。 3 | 4 | # 简介(Introduction) 5 | 6 | `JCC`是一个`C`语言的编译系统,包括编译器(`compiler`)、汇编器(`assembler`)和链接器(`linker`)。最后可以产生`x86-elf`格式的可执行文件。`JCC`的含义是`Just Compiler Compiler`。 7 | 8 | demo 9 | 10 | # How to compile 11 | 12 | ```bash 13 | ./run.sh 14 | ``` 15 | 16 | 在`DOS`下执行编译脚本,能够产生对应的二进制文件,其中用到的`make`工具已经放置在`make_tool`中。若您对代码二次修改,同样可以执行上述命令,这样可以更新`JCC`。 17 | 18 | 编译源文件步骤,使用如下命令: 19 | 20 | ```bash 21 | jcc.exe jcc src1 src2 ... [-option] 22 | ``` 23 | 24 | 其中`src1`、`src2`等是一系列的源文件,最后是编译选项,选择不同的编译选项,可以得到不同的目标文件。 25 | 26 | ```bash 27 | -c # 将源文件编译为汇编文件 28 | -s # 将汇编文件汇编为目标文件 29 | -l [output] # 链接多个目标文件,输出可执行文件,其中输出文件名可选,默认值为a.out 30 | -o [output] # 将源文件一步编译为可执行文件,其中输出文件名可选,默认值为a.out 31 | ``` 32 | 33 | # 环境(Environment) 34 | 35 | ```bash 36 | OS: windows 10/11 37 | g++:(x86_64-posix-seh-rev0, Built by MinGW-W64 project) 5.4.0 38 | # 注意,由于用到了一些C++11的语法特性,要求gcc版本不能过低,至少要支持c++11 39 | # 主要有冲突的部分是unordered_map这一数据类型,如果编译器不支持,请修改对应的容器为hash_map 40 | running env: linux(Ubuntu-i386) 41 | # 由于产生的目标文件是elf(32bit),因此最后在上述虚拟机中测试 42 | ``` 43 | 44 | 附:[虚拟机镜像地址](http://releases.ubuntu.com/16.04/) 45 | 46 | # 细节(Detail) 47 | 48 | 参见`document`。 49 | 50 | # Demo 51 | 52 | 在文本编辑器中输入以下`C`语言的代码,这是一段求斐波那契数列的例子。 53 | 54 | ```c 55 | int Fibonacci(int k){ 56 | if(k == 1 || k == 0){ 57 | return 1; 58 | }else{ 59 | return Fibonacci(k - 1) + Fibonacci(k - 2); 60 | } 61 | } 62 | 63 | int main(){ 64 | for(int i=1;i<20;i=i+1){ 65 | out << "fib(" + i + "):" + Fibonacci(i) + "\n"; 66 | } 67 | return 0; 68 | } 69 | ``` 70 | 71 | 在命令行中,输入以下命令: 72 | 73 | ```bash 74 | jcc.exe jcc ./demo/test.tc -o ./demo/fib.out 75 | ``` 76 | 77 | demo1 78 | 79 | 执行完成之后,屏幕显示成功输出文件`fib.out`。 80 | 81 | 把二进制文件`fib.out`放到虚拟机中,执行。 82 | 83 | ```bash 84 | chmod 777 ./test_dir2/fib.out 85 | ./fib.out 86 | ``` 87 | 88 | 最后运行结果: 89 | 90 | demo2 91 | 92 | # END 93 | 94 | 更新中,目前支持与不支持的语法: 95 | 96 | - [ ] `struct` 97 | - [ ] `*`(`pointer`) 98 | - [ ] `i += 1` `i -= 1` ... 99 | - [ ] `i++` `i--` 100 | - [ ] `enum` 101 | - [ ] `do-while` 102 | - [x] `while` 103 | - [x] `for` 104 | - [x] `if-else` 105 | - [x] `condition` 106 | - [x] `&&` `||` 107 | - [x] `switch-case` 108 | 109 | ```bash 110 | i++; # 暂时不支持自增和自减 111 | i += 1 # 暂不支持所有的这类表达式 112 | ``` 113 | 114 | 当然更加复杂的C语言结构也暂时不支持,例如结构体`struct`、指针以及一些`enum`关键字,上述不支持的语法,部分在后续可以得到完善。具体支持的语法特性见`document`。 -------------------------------------------------------------------------------- /document/JCC-document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/document/JCC-document.pdf -------------------------------------------------------------------------------- /document/README.md: -------------------------------------------------------------------------------- 1 | # 学习笔记 2 | 3 | 学习编译原理的笔记,仅供参考学习 -------------------------------------------------------------------------------- /document/src/CFG-design.drawio: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /document/src/CFG.drawio: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /document/src/DFA.drawio: -------------------------------------------------------------------------------- 1 | 7Ztdk6I4FIZ/jZdthQRQL7sde+aip2qqrNrtvYwQlZlI3Bhb3V+/ARIhoOBHA1Y1czFFTg5JSJ6T9xDsHhqv9t85Xi9/Mp/QHgT+voe+9SB0ho78PzIcEgNCdmJY8MBPTFZqmAb/EWUEyroNfLIxHAVjVARr0+ixMCSeMGyYc7Yz3eaMmr2u8YIUDFMP06L178AXS2W1AEgrfpBgsVRdDx1VMcPenwVn21D114NoHv9LqldYt6X8N0vss13GhCY9NOaMieRqtR8TGk2tnrbkvtcztcdxcxKKS274zQ5usHlfuzN7//Y6898nb5MnV41NHPR8EF9OjyoyLpZswUJMJ6n1JbW+MbaWbpY0/iZCHNTq4q1g0rQUK6pqyT4Q75nrf+Q1UNff9tnCQRW8Lf8gvrolGWQ0srPPrkwbtuUeKXlgjRjmCyKq/NREfidsRQQ/yPs4oVgEH+Y4sEJwcfQ73vqLBXKEEKhosQYKBhUsFgJmE8m41F3pYj5zjg8Zt3XksDnfj2zY7CfPRn5cQ1DmLy+SEehSZk5SU8zbFewNbmDPwOIWEEM55ncNXFSIUew7upjSGJc0ji0QCO8kMLN416+NavcD0y3R25tL5XBfZvJiIeIpSQxzFpOULqP775bpiqdNvBLP0kFSu08rdStANyOHmbRkti7NmR7zvFAqZSLiYrcMBJmucTzzOylU5rLH23TMTbSYx504qvLYKvBUBcUzQl+O+/qYUcZlVcjCqI+N4OzPUSQs9YSveBXQCJO/CPdxiJVZEWjJJXzBNFiEsuBJVgg/PsgH4YLsy3kqrv+5nUTL0i4VMW1aZuTLATURM/qa0QwvjGbUZjTDpqLZ6qL5pmiGef1tO5p1dt5UYvgE+gA42eyw7+j60wliGvv9kTsw498d2RU7gLHzRO3+IjyQUxctaOqeN37ivoEaygJuSh/RaGjiOHBL08eC/whV+IO7/CEoT2eRc5+/Narwt+/0Vy/NtabX+hXgqynypZFlt6nIqClFhp0i36TINng0RYZthLOSZ62+1ec2hiy75iaArCpZrlt17Qv3hnpOfyDKMeXWc/rjWAOzH1QuTzAvT9f6u+XpQfG5Df+a5M9+kHi5MI21srFiVcRJCyHRSiKaJ1l/NTibaEFU5l8PafYJLe+ENF3CBxNSp6nUC3Wp143EODlinAIx9gli7LqIGbaoJNkvZuVK8omacOmhZjuHE/lsourwIOdf+E6a9wdOmX9N2cpX/RjmXIjavRn5fe9e12vGHHumZIzjzRiCKQ4l3ODnNCsY1RJjOackZirnTdwjM3KXFiYUiRTk9GEeUJozFXb+aM8PPEyfVcUq8H16TsBM1foE0cifKLqwX1SNU3kGdOqCZvig0OAOmChbyMuCVcxL4SleajvgGXW8PDAvyM2f4bfMi2644+UxeQGn0872eLn+Nz0dL83xAu3qt95mebn+G1UzvMw6XnrpN+QjL6Dt/eXUOWjHy6PwYl/wg8FmeXnUl+qOlzh/yf8kre33I+h2vDwyL/n3o/r2F1lM/2wmOYFN/zQJTf4H -------------------------------------------------------------------------------- /document/src/FA-demo.drawio: -------------------------------------------------------------------------------- 1 | 7Vpbk9ogGP01Pq6TkPvjanfbTi/TGTvt9pFN2EiLwSKu2l9fSCAJMdG06u62Ex+ccPgChHM+TkBHznSxfc3gcv6BJoiMgJVsR86rEQBeZIlvCewKAHgKSBlOCsiugBn+hRSow9Y4QSsjkFNKOF6aYEyzDMXcwCBjdGOGPVBi9rqEKdoDZjEk++hXnPC5Qm3LqireIJzOVdehfr57GP9IGV1nqr8RcB7yT1G9gLotFb+aw4RuapBzM3KmjFJeXC22U0Tk1OppK+677agtx81Qxvvc4HpvEu+jhb+9/Rz9ulmR+N07dOWrsfGdng+UiOlRRcr4nKY0g+SmQifxmj0i2agtClXIe0qXCvyOON8pquGaUwHN+YKoWjFetrsTBWscuSXwLQeCCGjglVSYVZZ29dInxPACccQ0uMX8TjcvrovGPFWqWpIF3VDx5PJxOydUQSu6ZrGOQtCxgyCyEhDDKHSuIqVZyFLED8UoVl4jKkbOduIehgjk+NHsHyo9p2VceesnisXIgKVSzw6UsnTmgWgc1T+u2WIxRNVIJZRrxuCuFraUAavubsvM3Znl277x7uF4O/AOxYuLYsS6VJvSCsq1/wd5YGuqnykRvHoa2EdS4HLKbZ2b4ET11pg7SEzXAB8hWSO9xvpEDHVyLy5Snk9FATzQXEIVff7PNdUVV6ucgWsRAPzltqrUrVi6GTHEoiWzdQHXemzqhBDhVVIPmznmaLaE+YxvhFuadOdeketFkljagayK6QLHqoLAe0QmpblMKaFymctoJvtYcUZ/lE5lqye8hQtMpDy+IJbADCpYKc+WayokOM1EIRYakevmJMFM+CmmEhQ6ke1NOoX0iBhH2xq0rwdd64OxmcC2G2hkUzmsV4LzmrtWN5+ipFYZu8+b4ZYVmFbnRMfyvNXq/nnbKl+ISnmEF/Gppj3aR3zKjsLT4o/5WhQcir+Qr4FnUP3fSbTbe3p4VHgRqTpeQ0JBOA4a61OHWs9FYPBUHmgPHlj3wD3Da9FvpweCpm5ehgPazn//ktu9OPRYRE71u5PICZ8q0cGQ6GdLdMd7oS+7bVungcpDVLruy1yzradaF5xhXTijmBqrgueUL441NbmtatIvD+fXkndcS7AX3WJmuMlrQUmDpwdMSAPaY0DOM44huVYVC5wkpEtIpnoM0qe5eoA1g5nYFFofZmda4Zu71XYmdVSdR3AxHv3jPN4PPJoZ2TiFtn2rF4m2s7fjOx+PPTZ3Qz42jhebWyvQj8fLJWOPU+ohGRv74+ZPQn1J9MfgUskIerxoxQOPJo975uiPw/B587Ftp/NiDzl6knSWU5Dy3xWXPPI/jTr9Y9OBFFyJ4fMhDY00DBs/RPhh62bjPFkoitV/VopT7up/Qc7Nbw== -------------------------------------------------------------------------------- /document/src/FA.drawio: -------------------------------------------------------------------------------- 1 | 7Vpbk9ogGP01Pq6TkPvjanfbTi/TGTvt9pFN2EiLwSKu2l9fSCAJMdG06u62Ex+ccPgCyDkfJxBHznSxfc3gcv6BJoiMgJVsR86rEQBe6IlvCewKwHHcAkgZTgrIroAZ/oUUaCl0jRO0MgI5pYTjpQnGNMtQzA0MMkY3ZtgDJWavS5iiPWAWQ7KPfsUJnyvUtqyq4g3C6Vx1HXqq4h7GP1JG15nqbwSch/xTVC+gbkvFr+YwoZsa5NyMnCmjlBdXi+0UETm1etqK+247astxM5TxPje43pvE+2jhb28/R79uViR+9w5d+WpsfKfnAyVielSRMj6nKc0guanQSbxmj0g2aotCFfKe0qUCvyPOd4pquOZUQHO+IKpWjJft7kTBGkduCXzLgSACGnglFWaVpV299AkxvEAcMQ1uMb/TzYvrojFPlaqWZEE3VPxy+XM7J1RBK7pmsY5C0LGDILISEMModK4ipVnIUsQPxShWXiMqRs524h6GCOT40ewfKj2nZVx56yeKxciApVLPDpSyVOYBEI2j+sc1WyyGqBqphHLNGNzVwpYyYNXdbZm5O7N82zfePRxvB96heHFRjFiXalNaQbn2/yAPbE31MyWCV08D+0gKXE65rXMTnKjeGnMHieka4CMka6TXWJ+IoU7uxUXK86kogAeaS6iiz/+5prriapUzcC0CgL/cVpW6FUs3I4ZYtGS2LuBaj02dECK8SuphM8cczZYwn/GNcEuT7twrcr1IEks7kFUxXeBYVRB4j8ikNJcpJVQucxnNZB8rzuiP0qls9Qtv4QITKY8viCUwgwpWyrPlmgoJTjNRiIVG5Lo5STATfoqpBIVOZHuTTiE9IsbRtgbt60HX+mBsJrDtBhrZVA7rleC85q7VzacoqVXG7vNmuGUFptU50bE8b7W6f962ygeiUh7hRXyqaY/2EZ+yo/C0+GO+FgWH4i/ka+AZVP93Eu32nh4eFV5Eqo7XkFAQjoPG+tSh1nMRGDyVB9qDB9Y9cM/wWvTb6YGgqZuX4YC2898/5HYvDj0WkVP97iRywqdKdDAk+tkS3fFe6MNu29ZpoPIQla77Mtds66nWBWdYF84opsaq4Dnlg2NNTW6rmvTDw/m15B3XEuxFt5gZbvJaUNLg6QET0oD2GJDzjGNIrlXFAicJ6RKSqR6D9GmuHmDNYCY2hdaH2ZlW+OZutZ1JHVXnEVyMR/84j/cDj2ZGNk6hbd/qRaLt7O34zsdjj83dkI+N48Xm1gr04/FyydjjlHpIxsb+uPlKqC+J/hhcKhlBjwetIRkbPO6Zoz8Ow+fNx7adzos95OhJ0llOQcp/V1zyyP806vTLpgMpuBLD50MaGmkYNl5E+GHrZuM8WSiK1X9WilPu6n9Bzs1v -------------------------------------------------------------------------------- /document/src/FIRST.drawio: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /document/src/LSMP.drawio: -------------------------------------------------------------------------------- 1 | 7VrbbuIwEP0aHqkSOwR4BErblVqpElK3u29uYoJbJ2YdU2C/fu3EuXMrBYK06UPJzPg6c85kbGjBkb+652g+e2Iupi1guKsWvG0BYPb78r9SrLXChLHC48TVqkwxIX+xVhpauyAuDgsNBWNUkHlR6bAgwI4o6BDnbFlsNmW0OOscebiimDiIVrU/iStmyS4MIzM8YOLN9NS9jja8IefD42wR6PlaAE6jv9jso2Qs3T6cIZctcyo4bsERZ0zET/5qhKlybeK2uN/dFmu6bo4DcUiHUfvHuPP7wXUf+cPg6eX93u89tk1bL06sE4dgV/pHi4yLGfNYgOg40w6jTWM1rCGlrM0jY3OpNKXyHQux1sFGC8GkaiZ8qq1yxXz9qvtHwi8l3HQS8XaVN96utRSvVS1wqw+0KmQL7uBdG9dQQ9zDYkc7kEZKEgAzH8v1yH4cUyTIZ3EdSEPRS9tl4ZAPOiJfiU487ieiC5yAzKZyucM3+eCJyCWxYsqkB/JxtP8sWGJoh1EkBrIBgPNVZkxGMZJh5DLjkYqjS3VuxjJgKJVkVcBYzojAkzmKPL+U6aIY9iJuUj4ok8N84mgDRW+YDlN2jRhlXJoCFqg5QsHZR0pVU+/wDvmEKpi8YO6iAGm1RqApQzhElHiBFByJFczTjXxiLvBqN56q8U86wE7cRSe/lOzLLJV0dJNZLokkOeTkiAGwVj63jRvD6BdJbdn2HlpH0jPmRPpARebUXAcHct2qk+tgA9cboiVEA9C4LqLB06dms78pNZtNaj4SMd2bcnLuVDBjGVXMWOfCjNVQfEfAICiHy6yX4p1LURw0FD8OMRBUKG7XS3Fg1VJ/rYh4zT3nTlNSyqouJRSKrrRm65Vqtq5Vc82WXA/sLdrMek9oRpPTd76EzQI/oVHl50VzunmGI/XmpA6bpH4kZHqlpA7NaiFw0aRuNmez3YWbXSJ5t2aSX+xwZjUkP7JygxWSg5ort34tldu2m3BY96WZaR1agNVaf206U++m+hQ5RaaPIg4BY4KCUH48TfI8P/ZGPZR+E9/JDpJcooiVmMElWk8JpSVVhbCKqsRBdKANPnFdui3vFCF9Aq5bpZs7WH2b2xuIDs9G9ENK9sAdqO8WlRcpCkOVY/cduJLnPcet6//KyzQ2xzP/Ot8QsER3MPH1DM+MRLxM4VLECwQlIMT71L0yLFQH6pSA1y0NFDuiMlAEqnTb38DZ1++PLpOa5CfyFdVpKRn9vzkKlECX/johh3lw0SRlXyt4oh4NYuDVIaZ7pYhpN3hR1l4JL/268dJr8HLFeEnxcX68SDH7FVpc/WS/9IPjfw== -------------------------------------------------------------------------------- /document/src/NFA.drawio: -------------------------------------------------------------------------------- 1 | 7Vpbd6IwEP41PrYnEED7WO1lH9pzemq3u/sYIQLbQNwQvPTXb4CEq9faamvxReabSTJkvpkhaAcOgvktQxPvnjqYdHTgzDvwqqPrGtAN8ZUgiwwxexJwme9IowIY+q9YjZRo7Ds4qhhySgn3J1XQpmGIbV7BEGN0VjUbU1JddYJc3ACGNiJN9JfvcE+iGgCF4gf2XU8u3TOlYoTsF5fROJTrdXQ4Tj+ZOkBqLmkfecihsxIErztwwCjl2VUwH2CS7K3atmzczQpt7jfDId9mwHP/gT+S+Wv8OD976j7Cu6ef4ExFIeILtSHYEfsjRcq4R10aInJdoH07ZlOczKoJoTC5o3Qiwb+Y84WMNYo5FZDHAyK1wmG2+C0EoIQ/Zc3VvKy6WkgpczTxbuUGSCiiMbPxuruWPEPMxXyTndzNW0wDLPwR4xgmiPvTqh9I8tDN7fKhD9QXHupA5owI1Dkof6xsBplAugGqM2ZuykmKAF8yhhYls0liEK1ZVhF3UZVvVrrZ3c/e2MteXGR3qKRSCAoo5fgufFcUOT7fwbn5+Riv78n4UvTeEJxs3ikiMVY11SLC3f6Ypswpomb9i6lSnEXpxl8KA5EF80Iprlz5nc4yUgBQiHBzVLcSWLacgut8IUT0poQXM8/neDhB6c7PRHushj3tDSlvkmDm5T9R2TTwbakgaIRJP28mA0ooE6qQhskaEWf0Je9MmrzlGxT4JKHJM2YOCpGEJQM1EcI+Ir4bCsEWXMEsv5EpZhzP1/OpGf+iclVSVutJeVZ0TlVlvFLPNMFHMUb/numsb5nO8JjprB8qnbU2nd+UzhB+tnSG3zOd4ZbpbBwzneHKdI4mKHzHdNY3pHO2XJvO9XQ2jE+WzsYSxrThUuEyrU8WLvNQ/RrmCFuS3m0H34VDZo1DZoNDxhIO1V8xvBuHukdt4Ocwl7MeDiDc0MVT6QEzX9x/EpUv/app51dC9RJkbXhlA6119h/0ysb8ng+FmnEg6uz3yL6sydfq/c5tBFbbCBgjuzpgkJZrHQxRKOgN7ofNrjMU+8ZXtpBl3aZGMlGVeZUUWemv9YOxT0gNalT6pMb7NiKXUhH4jkNWNaxql3qHJqHVj3kXzQcNa0mTgB92zLP2P0rArZ40asx7C4/QThza7pByMtTSL2rU6jappR+UWt2WWidCrfppFh6bWr0vRK3R2iNWS7b6Oar+w8bR69hFS7ZTJVvjh3jjyGRTi7VkOz2yGeBglU2Ixb+ZstN/8ZcxeP0f -------------------------------------------------------------------------------- /document/src/RE-NFA-demo.drawio: -------------------------------------------------------------------------------- 1 | 7V1tc6s2Fv41zLQ7kwwS6IWPcW5ud2e2O5292932I7Zx4q5jUuzcJPvrF2yEQQiQzYsgPnc6jS3Ei9Fzjo6e80iynPvn958i/+Xp53AZbCxsL98t54uFMXIcFP9JSj6OJRSRY8FjtF6mlU4F39b/C9JCOy19XS+DXaHiPgw3+/VLsXARbrfBYl8o86MofCtWW4Wb4l1f/MegVPBt4W/Kpf9ZL/dPaSmy7dOBvwbrx6f01pykB+b+4r+PUfi6Te9nYWd1+Hc8/OyLa6X1d0/+MnzLFTkPlnMfheH++On5/T7YJO9WvLbjeV8rjmbPHQXbvc4Jf9w8s/VPf/vXrw9B8CuZsd/mb7sbxNOH23+IFxIs4/eTfg2j/VP4GG79zcOpdHb40UFyWTv+dqrz9zB8iQtRXPhHsN9/pI3tv+7DuOhp/7xJj8ZPHH38Fn+5sW9tOyv5PbnirUs9UfDlPb3H8dtH/tsvQbR+DvZBlBYef0fy8JXvJy3aha/RIqh7KSkM/egx2NfUw1krxtYRhPHTRB/xeVGw8ffr78Xn8FOYPmb1Tk0Vf0hb65yWO173u795DQQA6SZ+3NkqjH9wbAl++iPpn68Jxmb34fN6ER/45m938Z+fv50OFRAgCpPr3OwObXgXV0D85T1/Bn1M/x5uOhcFf4qS3WtWZouy+JfminOlqrLj7xDFMko3m9hDJGh8e1rvg28vx1/7FjupItaKYM2MMDm0OLyQ44GNPw82s8yk78NNmCBrG26Te+z2UfjfzD+g9OV89Z/XmwSU/w6ipb/10+IU9ijGxszfrB+38ZdFDMIEqukP+R5E++C9HqhlYIkTaOpRUo/rpF/fTu5LFD3lHJco6xyJWIFEaC3RWo4zrtZyJuQ3VuA3OkUiviVFLGYFOTRiUkajKOu+F/OMxh9ZNHEMPUhD4NFhjEE0Y4yKJh0mxiCVvqJkdz05j/jlKpzHLn5t+0qLVzkHCWOxEe2LkDhaqmS+q/VmIxWVDDMxyXU8nLhLDzyvl8tNlX8pIrcDmyZS56IyaKroXnozaG4cMshVQeYH32L38x//4s/nAJwEAFJYgsthCVPhpq+wxDOPG0/taoIXlD1KlD3LA7E4tTzv8IFZs7t/PihqtUBascUbgpU83izsLEnAl24JnPERjucOpd1AyLWLEEJlCCGswBDtLbRFpbc4RDDxvt7/lvucCyXib6dIIvlSYDDMBiBYm+VgJkMQDDzHtY5XMueR+RfTRAcwHeeNL823GLAd14tGGYvGyQ4Bc4hPdOITXYakCgcDxSfAkYx9qEvkMELlCMiQJAmmxkFTz5IAbpKjEnC8cjCjRE1vw1tFtDny7iPJ77u42Ie4nDX0In3n948jWp2uhRvtWli3wWtFKJpFoi/+9vII98+cbzhe6cKrE9XVUcPVITY+z7N5IxtZO87kXJvByJjrui/PqPuqTgVdm/vC4L66dF/YHZv7csF96bsvT9d9YaPuqzojeW3uywH31an7Gl30VUtHKFCzOL7dBDHR4/yH+Lni/+J727lPPyYfD1zEAWOr9F3fHWpQ//nlcNCJXWfc3MHme5CM9EtHihfJARUnQC0cOz5lcnAbRs/+Jju8ib1oEN3EyF2st4/KKglncZO2dXI4be7C4XUMw6SBk+N27u6Hg/sotvlVfFFx+Rh2osJbGC2Ld8+ffppGcCO9Vuzy7HVi1zt9JsnLrfIsg/JF8wwnUaMD0KeOGjxCBybo4EZqBw1K7VQP9cECwQJ1LHDU9pZpycZib7UyRS17S40ttTS1mZ2sqtKC6synyXbqDKfaaupNpsZedIwls5TMTA5QHIOl+NOwlLH1TGMWZp4eJQs/kqD/hygb95xkFAUK+VSsqorVVX/sNthpI/Bc8UWwWFgKgeecE5d0lACTBZ68nDYdVuApeJ9RgtFpD8ZT4nUEEFutsBpiSzqnpC8NMVX4u0ExRliZqwAur8og05R0I5dH2op00lN/CdcHs67oLRH3bpEbOyqW/r94weNjpteQcJI9VAvoXDKZ7QKwLF6j7wewFeey3WJ5Kj3ntAELfafatQHitiV71QBBXJ7m4mpB4i6K/I9ctZekwq7mPhQX74Pd/OXK9Ynbrr6NJAQfn7hTPIvGm4R6FrT3nSoEXFZ0rMwt9cuDctSuSskN7VWjvTfeYu6EvAdo73vV3jNqWnvvEgjr9aM2OlTU1q5NzcuoQXt/nvZe6QgG1d67tak289p7gM0BJ/KwDenipjdeCCZvnbG6je7kcuKY7EDEY4LGCxT2PUtUTY/GiGK4DO6r1ivpxL9m3VfHs9sn7L4wuK9eJarG3Vc1mTRXogYEciCQ+1QSVUTLJjioEojUrnQAJggm+Lk0quYNDkSqIFIdp6mgkZmKUIONUhjoliOQgzDwrKYew4+JsrFao5LRYveq2rii9tTexJikwKuAVug0mTe3e5ICZ/yWMZ0mhcVe9QktqktoHWOg3nWamLoGdZpCqwc6zfMBQtsynpo6TeZpQaK1TjMluqp1l05d/X50l4xegM8C2C4A62cCE6norPoGk9sEJvVz9Qom2nGSAES8k2HxZRHvYcxrksWnKhYf2qtaxGu+xapJ3/F5DxDx9inixUSlwRpUxEsvCYyudsynu8pp6yisXZua12OCiPcsEa/aEQwq4qVmtg2cpiMQea1m8gebdASsmsO/NjUTiDF7FWMaj6oZcNdnuC+sG8e4Rt0XBvcFYswhxJjm3Vc1pThXogaUYKAE+1RizMy2TAlemIpJBRMEE/ykYkzzBtde/QxiTBBjDiDGNG8q7RezBlMBU+nBVLLVJbNV11RM9rDG0l7kD4EcBHIjNjlJg8JM906QOtLnXrku98rb7pSpVsxxp+iwXUk2PKxuWGhUQTd8AUDa5hbVAGESNyqW4O1Y6ckEu5/ehtULPRl1aqr3o/Pkl+SURiQaNo4kOTbsRzMsIwk3IUn5VP0iqeNMFiiGJ5NqYkSK1gxnmjis+lvXXJ5bEgybbjBY9Pd6wViEomNcLsxhzd8z4i/dNX9bx1/t2hTW/B27XJhKMavSEQwqF+awp88ZjoBrOgKv7Vzxdm1aTZxfm94O5MKdBjJcnu9gOqYGxlrfewk+sDmMMTrrSTwmeC9QC3c8DJNX6jHsvbzqNdbVCe5OUtZVSeUJZm5BDBAVD4MYoMbzR42uckzqAE/K7wolgClxgFed+gBnNWYgcT4yIJ07RebzA2kaEkGOpAyYaSCdO9Hj8wNpGh6JsSKQiGkgnTuB4fMDaRoeKQOSMeTw8vi6d2XRGKgk3YyYx9QNOBCVBBmx0WfECLllUnZcwcsMmhNDgica1qwnyirrrqXleUZdQfXMq/Gpb0C516lyD+Oyi1Fttjso+YvsS3JX1+pkPE0ng2xq1Mt4TV6m2W0oA4a+fVXtTS/zVfdnuat2w61F+vN3x5//vFMMuypTdxpbdoDjvcjx8nE6Xki7TXS4T8t4Qoa3V0I2NkoBnHrh3/PHqua8Kbp/8Vnd+RsZKbQlDS6bfuTyErrSxVQrpyA5rOGUfqYhIRtyKBOlvknZhSnWrBvYhbkTcmEmRhWtqYuLHBJHZWrMrXdIqlNSjrzSh3llH1Y8pS8fBlmXaYZhNbg058PEegej8GF2gw8TYdiJefk9d6T3QCwlSUbP2SJkpGOaJkWm36gIGdV3Zw86IBU/fnpLflhtXWpX1Beu+qEaXc8Vc1zcVeQvzXNcovOF4GpiA0RVcGWc40IY0DTNUN11SmgS4gZzaDKxh2suVGfYK0ZpNuNNAbtqrTDTUTzS3UvWDH3hIbuMvXouguOy87vklAaSxHYbTumJ8UBGMv7KoYluoqCI7cFSBWdg20iuQIVt3pAriKPC+lP6Qh0sFFXbRXrjDOCBHZ1oAM/GGMCfu+7850fTNAJ4zy4npY0H8BjIhYn6JlIeDor1eM2hqVqOpauZ9AxIJmvvOQpKeRDa2DmHNgbFZGMwyqVItJxXjQe8ypUib3ubDiMGDD2vyPNtH7xkAtzcag0PxOLU8rzDB2bN7v7x9a4NvoqwacBYfgZVbBmr1QovFpY83So+sqRzSmg3MEC2XcQBLs9z9FTDEbc3CJjl7CxjWVWsS0QgbHSP3exBYa6jNdq5jtLqn7xs1cPOc8RTWpIaJsX1uZw9d41TXniYZUuTMOPkGnNhhmvNvlreF+uBWR4R8QY/lBDrjll8lhzid9aMWg/U4rbFVeHKdUUm3FbgZuDYZDxplWFjE2GKzbGJU9GqA8UmTi1hBLHJCGMTpNgqddjgxHFMmPVExZ8O0nYF2KwrMDKQzLLZzHUKLZvszFHbtvGXku7jJCVBnlNsc8/2GlpdKSUxBIW2vUJFplt2JVQKGTvbL8wr3ufMrefQEHvPZc0BY6yrH2MhzIwPspxGLhdWqBhzvgVWqOg034Ls8VkoLGs6Ta0GE0tkCzAhFac2bHLdqZaRdc2pZZngMhfWsmd58BKmjbOUkJvZfuK7H+JPX6y7+4SUu2PWbJYdtg/0HLc8ipSnz3NcX1zx3jq4gXq3b5zfW/oBXyn5PbrgwXzVDYY9IsXISoeIXEUGuj+CzwH12jT1RkzseSrQ5GLD/lAA9/q4Yu0V9FzDBFH1EnrAFY+UK+YqvfywbLELS/bqOwPhhjWcgdmlAlwjq3pcE1t8BhTa9gsVrKwj7SqCqKxk7IovJrR4p2yaTyVj7Nr1Z/TEGYtGAc746hgp5kghswihjfFR7pXucZH2fVqu0eguF4iMJfapnx+c6wmxXVwv69bDTS3bf0+o39xtgyJ1b8MRvqW5f1K/KFt4R70iR47yPtXrBdbW76tHrFY3Q9qqtmuFtNUnDBK4lFg2HyRA0mqiFC1FRSh53HjSyu14gcCapJVbneDR3rpd6eLjl/MVVWWu5OyTVZGlkjNcp8QWzqFItTP81earOC2Dd9hslTv8TlPjDzJgectpRhrclal+45FGbX4IIo3RRhocS1BijvFIg8BWQNPUWsnCPWyX/dLAUMLlfuMqaFKizZsRo3vzZQ8KygJrKsoCTLBxZQGBTQjOcAbamxAQs1tLECNCsGtSFpwBhbb9gqaygOOhlAUePldZIJ/RUx6FDL/3BigLxjGUl5UFWTdqbCgvpsddX8isLcalZhduIEa0H59NWaDf3K2DoouUBR7tpVcsKQvS+2grC4r1++oRq/lEUBa0I/1BWTC9IEFSFpgPEgQjABTtxPh+WVmAqfnpsGwsSskpcDmi/TSiVG40SmVmqfdp7f2q36rdBKNnR42kuEA9duv1qNzGdfV7ihrFWwSRB4g8Jh/0ySKPEQR9GIK+SQZ9ssgDO57xoI/W5n2vEkwTFXmwsl8aGEodL5heo0wmWWkk12uvTMYqZbJCbpxomB1dbTL+WtgMZpSq5BVfBOpVsuecuKQjGYPnSkymEC3mgUsGVSVT1eLqEAJVbbwzghCoPS8N22LBtlifwjo9277FEi2gVIYNvzcWAwXxREcqTPL4IxipMBipTHSk4pQ2/cWKrfsGRtNwa3/SPgcrTi+DFRioKAYqqv0mBx6oMJVCUQ6Ftsu7KDpENWm4svR3T1k2J/dWk/Jf/H3sz7aHEmw7peAGt3j7zTmZ8rtvULKLspaan9Jmc7YcBB1zRSWZT+lKniddSXqWCrlQZ7kWpppQC4hojQiE3Vt52sSlmEiuxfTE1d3hQofSAFycjwtGOwIF013KrztMqFgTwMT5mCDy6Mi9EBO8dKGhMcFVCjLARGs/4dj2hZjwShcaHBNA20xzpM1Ky+KZp204BjBNE0yCvc0CFtwXlOKvUZi8opMbi3/R08/hMkhq/B8= -------------------------------------------------------------------------------- /document/src/RE-NFA.drawio: -------------------------------------------------------------------------------- 1 | 7Vxdd+IoGP41Xs6cBJKol61tdy929uwZ98zOXNKImp0kOIit7q9fIpDvaNQoWvGiDS8ghPfh/XhI7MFRtP6NosX8C5ngsAesyboHn3oAADjgfxPBRghs6AnBjAYTKcoE4+A/LIWWlK6CCV4WGjJCQhYsikKfxDH2WUGGKCXvxWZTEhZHXaAZrgjGPgqr0n+CCZtLqW1ZWcXvOJjN5dADV1a8Iv/njJJVLMfrATjdfkR1hNR3yfbLOZqQ95wIPvfgiBLCxFW0HuEwWVq1bKLfS0NtOm+KY9amQ7T58/Xr3zYeetE4iL55s/lX/5Mr58Y2aj3whC+PLBLK5mRGYhQ+Z9LH7T3j5FstXsra/EHIggttLvwXM7aRukYrRrhozqJQ1vIJ08132X9b+JEUPruq+LTOVz5tZEnMNZlg4xJI0ZKsqI933LdCGqIzzHa0g6miOP4xiTCfD+9HcYhY8FacB5JInKXtMm3wC6mQA5Qjv/cNhSusMOaFfLqPr/xixrZLIgRTwlcgr0fv14qoik/LrSYeeAMAFuusMtkvyC92GJEo8HnFGMVL/u/LON9cDPpLjbpcpROxlIzfaU6ck4opVsS5pmUkhiE3Agni3ucBw+OFmOo7N0NFPBUBme6zpMrf3o2oCNErDh/TXTsiIaG8KiZxMsaSUfIzNQG2XLoXFAVhgr9vmE5QjKRYQtvm2HhEYTCLecHnIMQ0vZE3TBle7wZqFVjKqirrqIzqUJbfMxOl7NA8Z5yUrHMowhooGnUpdUF4ZepybshyTI3l6BSKbgmKbgWKTg0UnXNBsX+nEYbXMsJoUOdlIgzvYDtx2K7fb1bsftGsiEHHfNnYKRaAbyBWhITYpaWtOw3CsCSqbMpkOwY8X3iQFVEwmYRNtqWI3A72sw2KrgVYVdfi1exneK79PGiEzJEIURmhktlVOORA2cJRWXWI6o2ee49uPXYaYPZRIQUGpWhlUIUUvCSkhnfqIlSQv99HaHUSapo3EU2aPLTTPLTkfWCN97loYmPXcSJGX2n071ybvsAN2Q6TiXaLRbeERc2ZqA3vNc5w2sYZVr1GLxRnHM5amWz0wtloieiEtuZs1HYbMXMURIpKXS5QfELKWQYv2pN+iuHuNSsdloiOGg79olmpPbhXdzFs6S6AXncxvKHQ0jahZZdpadkN6T5vA3UUidFXmgq416avW3q0wqSl3WKxlJbqPiAFWk5IO4wXAGwbL7g64wVQ9wyLSS+vKQcouQlH91kn2MlINOl7Kg1bonFehaLFdnUgdFKryfsKBEXLSoukl/AfbZJMWuMwwF6HcQdYSqlvZed1n3ICT4edv4J8Ergt/YPI6LT5h2Yq6fpiQnPM2WVMaMNyTKg7P+n4KZuz0pp1Lmg/32EI0DIIh1fmsCCoAaExGmmA4RX15QLNRgMenuAYUuOjYNEtYVEzqQEdHcFuh0ErbBu0ivcfdQWt8PCg1ZAaes/MXaiZ1YA7n/o3rMY1g6nMariu5iDRsSuLvd/QH2Ha/RV92y7kltRYB+x77vqHXODkOuMzkoKiMxpokN7FSBD1mvx+fwJO9Cey618k2Jr7JuBYJUSIicleGSgeKEWbXLNF0mDZPA5wB7XjvDTNy+vvas8vxAwyhKZrcgJoaxKZvaAtIPAYJq4GtPYRoLU/LGhPxtrgQKwNLoA12EzlXF9WZmjFbt/iL2dluhmC5kemDK14JxGjU/O8w0UjRveYiPFU59uhU3TavtktGnYeyVVPyVsFcp3FTnXZo7H5jTZf9y+B9G8o/DCk8Dlf3nQ1c8LOvT5Q77R9oP5cHsO2Plu5jyLnJS767mUdyOHP7RvKWu+PjniaGWvlHW+MsT4oW/moWAKlY/Ka04+O0g9ezH5NU1ir7BdL4fP/ -------------------------------------------------------------------------------- /document/src/Right-Linear-G.drawio: -------------------------------------------------------------------------------- 1 | 7VbBjpswEP0ajiuBnSWbY0Oz7SWqVGgr9VIZbMCqwdQ4C+nXd4iNDYpWW6mHNqteyPOb8YzfmCQvwEkzvlOkq4+SMhGgkI4Bfhsg9LBF8JyIsyE2ITZEpTg1VOSJlP9klgwte+KU9atELaXQvFuThWxbVugVR5SSwzqtlGLdtSMVuyLSgohr9gunuray0Nbz7xmv6rlzFO9MpCFzslXS14TKYUHhQ4ATJaU2qBkTJqbZzXMx+x6fibqDKdbq39mAdx++NfjjMSPdMf386eteJe2drfJExMkKDlAsoN4+B1BNYCZKCX1ggqQwmfGP03T0fSIbXkAgJW0PH8fUhybV+izW+VOdu/5y0W8gAaFuXO4wTaFIGBxQ8BAHu8tVTuttAs/cocIh6g6tFgVi0nSA2rzvFjJgQEbJWh3QV4r/7ghW8jOjNc+8eg9pdq3/5uRmr+vCXnpfLQodihxCDmGHNv9v+B9QsLjhG1fy8g/K/IJ6GHmIPMQebrKbm8Mffq3QqjNS8tRSNv3fhhAeaq5Z2hkdA7gj4GrdCFhF0xUIXrWABSsvx+VCJFJIdSmFy7JERQF8r5X8zhYRGufxfezaPzGl2fisJ4ic0wCHxmTDtDpDit2ws97EmrMI2/Xgrc79xnL10ubMicTaq8qV9g4EgDUh89KbnUts4Rjx4Rc= -------------------------------------------------------------------------------- /document/src/as-递归下降.drawio: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /document/src/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/document/src/demo.png -------------------------------------------------------------------------------- /document/src/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/document/src/demo1.png -------------------------------------------------------------------------------- /document/src/demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/document/src/demo2.png -------------------------------------------------------------------------------- /document/src/epsilon-question.drawio: -------------------------------------------------------------------------------- 1 | 7ZrLctowFIafRjPtIjO2hB2xBMekmyw6zDTtUrZl8ERG1Ihbn77HV7AxDSSChMIiRP4lH3F+HdmfZkDEiVePCZuOn2TABcJGsELkAWHcoRQ+U2GdC/i+EEZJFOSSuRGG0R9eiEahzqOAz2oDlZRCRdO66MvJhPuqprEkkcv6sFCK+qxTNuI7wtBnYld9jgI1zlWK7zf6Nx6NxuXMpt3Ne2JWDi4ymY1ZIJdbEnERcRIpVd6KVw4XqXelL/l9gz291RdL+EQdcoP380UtFs/C4IPVr+S74a1+/bgroiyYmBcJI2wLiNcPogU0R2mzlLymEEqYGjJT68Iu+/dclh13s2wxezAA4+lq07knSsj8ehBHxpEPHUM2mcG/p+FuiMcsfh4GMs8j1aPvl3fSAe2IrN/yfc9orotR10Q9I/1C8JdeUxt1s33Rd7S5o6cE2v14Pap5SGG900HYIka/4aCnz8DPnDpuph7o21afOW/SsuTIcVHfuor0OzDCaaTvX0XmVkvm7Coyt2HEQyNzri3z97ybcS05nMj5JOAp0xjQvRxHig+n+at4CQQK2ljFAq5MaDIRjSbQFjzMHImEcKSQSRaKBIzT0Ad9phL5wrd6bJ9yL6ymX/BE8dVe7jIrmgMK5jLmKlnDkPIGXBDhukTEAgiXG540rUIbb7FkRY6sYNhRFXuDedAoSO8I6sN7qU8P7Ly9GCnqu6hLkGshauX7kaWnh6P34XuqplEmYRhiv7VMAtuzLVtPmWBqvF4mtKVMrFNVCfn32aBlkSF7dVfsuXSVs22398F10LPvZEcH5NqIuqhH01rrDRAw8SFnicMPDVqYWIfJ2ixrPUcYX6qjxldt9p33qXOuqg5ZHIl1HgS6WDzN7iOkkz5/uFhwFflsp+dE5b+1jkF2IMxnnXizfPLNwmJ9C3vFHrdZ3JQqy8nNcg2Ws2Mst/RZfm5CCSxOg9TTHUKh2CP2qQjFPpBQzPtTIUrnEkH2uGPVxYFsxz4AZO1zgqx1A9kbyH4MyLaN/Khy+TTreHkgcePjGx//h5YjN3tddAet1U3gnTu4XCgOqc/bacejVscyqvn00k4bFLfRzlugGC43vxfI+rZ+dEHcvw== -------------------------------------------------------------------------------- /document/src/for_loop.drawio: -------------------------------------------------------------------------------- 1 | nZTLbqswEIafxlK7iAR2QpplS5JejrJikbXBBtxjMDFOIefpO2BzU1upOpsw/mY8Hv+eCSJh0T5rWuUnxbhE2GMtInuE8eZhA78duFlAyNqCTAtmkT+BSPzjDnqOXgXj9SLQKCWNqJYwUWXJE7NgVGvVLMNSJZenVjTjX0CUUPmVngUzuaUPeDvxFy6yfDjZD3bWU9Ah2N2kzilTzQyRAyKhVspYq2hDLjvtBl3svuMP3rEwzUvzmw2vx/NbdTkfBb6sT+9/3oLN6n3lsnxQeXUXRjiQkO8p7ko2N6dDcLl2dT6lqjSrun+lRwjApGonJ1iZ+8ohuNOcJsskoSpEAo6IljV8TtE8xf8emip9hw4Y7Xz06IlS9D639qE7mDBClTOIheH6Hm3HcmM9uwAtKjDKuK5sVb9Abdt21KUn36Td7gcIz2TVWSoGOJ4YXqiBtbqWjHev6YG7yaH+qLLaNjB7wHJTSFj5YFIpMrjtXvK0V0dIGSqpdJ+KpGmKkwR4bbT6y2ceFsTBJhiP/+Da8PbHjvPHPob556rgRt8gZNiwc63vZt/funUzTRJZO5bPp8hzkLrpzcbcU4OD4Xp8WE6z1Ptmf0jk8Ak= -------------------------------------------------------------------------------- /document/src/指令.drawio: -------------------------------------------------------------------------------- 1 | 7Ztbb5swFMc/TaTuoRL3kMeFdW03VZoWTXt2sAleATNDmmSffodwSQgmzbpwSckT5NiYY/vH8fE/MFItf33PUeg+MUy8kSLh9Uj9NFIUWVI0OCSWTWrRzcyw4BRnlXaGGf1D8isz65JiEpUqxox5MQ3LRpsFAbHjkg1xzlblag7zyncN0YJUDDMbeVXrT4pjN7WaynhnfyB04eZ3lo1JWuKjvHLWk8hFmK32TOrdSLU4Y3F65q8t4iWDl49Let3nmtLCMU6C+JQLpvjZ+vHl/tvXjfvrJXzQ+AOnt1krL8hbZh0eKYYH7U3nicvxJhsH4/cy8XPqsCC+jbaz9BEqKEq43hXC2SI7ennlZMyRXW7EYj61oWCGgggOT7P9Jt56UxpEMV/aMWVB0QWeF4acOHSd22GMUtfK7oJ5vrMpJVcUzpYBJslQSlC8cmlMZmHasRWQDzY39j34JScOU8+zmMf49lrVcYhh22AHD9kz2SvB48lckor7vRAek3Xt/MoFNfC4EeaTmG+gSnaBmXGWPWiKlP1e7bCVcxbdPWSNzIayJ2VRtLyDCU4ynv6BLeXdsIUw5iSK0nqDhKug6Rhdept0qe+GLhYSjgI8YLpU/QS6tDbp0t4NXRFZ+GRLzAFYDKYMUi4Bcu8bNm1yAmxSm7DptbC9iZTybEUhCv4f2WLCZ481HBS29IavkHRWahylhhpjbujGubKr16kx2oTGuCBoYFv4HTr5NEhyjFPijdwmOuMLQoeFNtutUYMCR+/dQmVeEDiYRqEH7uwnP4PCxzT6llRPLggf6vuYoniYkQeiSt/EpHyBFO/IOtxfgV/SaAydkmBMpemmhEyr2yciY52MRWxMjLGKzpYIl8kwTiRDb4yMoxr2lYzWyKioOCI0RAtOc2gclaCvaLSGRkVzEaEhSmWbQ+OoftwhGnKBhtIxGhgR0xHmGoZtkrnT0C6nezSOir/XqNEaGhXlRISGrLeJRr1Ue0WjTTQqcqwADZEc2xwZ9Xps52RYMJYWuGNpg2Cjunvtfo9Sr5xd6Wg5chzKYt3vUup1sc7h6Mmi0s4upfKSiwgN0UsujaGRB6mLkEwH/S9fETIydtRJlR1dFFa0xtjpqy7mMwxlN4lvcxp/6CqmOKZNxFzMTV3Tz/S2ySEXmiqIKZNWY0pfRTGedCchQx0EGbpyAhmt7mGUvmpinCygQ+mrAAOhQ1V7FzfqZbH+5SKzx+lNtP2KA3oFU71OoEER+SDGY2DJiS53npz0VUiLouHmJrreeYzpq4qWxI7hpiZCMNpNTerfWewWjHxxGQgZh2lJkyEDfu6+jtyW7X1jqt79BQ== -------------------------------------------------------------------------------- /document/src/注释识别.drawio: -------------------------------------------------------------------------------- 1 | 7Vpdb9owFP01eZnUKrETAo9A6aZqkzohbevT5CYmeDUxM6bAfv3sxPkGSlNCeEjVh/j6M/ece65jY8DxYvuZo+X8G/MxNYDpbw14ZwDgAmCof9PfxQYI7dgQcOLHJiszTMk/rI2mtq6Jj1eFhoIxKsiyaPRYGGJPFGyIc7YpNpsxWpx1iQJcMUw9RKvWn8QXc221TDOr+IJJMNdT9x1d8Yy8l4CzdajnMwCcRX9x9QIlY+n2qzny2SZnghMDjjljIn5abMeYKtcmbov73R+oTdfNcShO6cDv/rJn6+HFQfD7w+DhngW/f9709NrELvEH9qV7dJFxMWcBCxGdZNZR9M5YjWrKUtbmK2NLabSk8Q8WYqexRmvBpGkuFlTXxnOqiQ6+ijat2Jp7+Mj6E8YgHmBxpB1IHS55jNkCC76T/TimSJDX4jqQZlSQtsu8Kh+0Y9/hZD3uK6JrnHClR+VyR8/yIRCRS2LDjEkP5PHo/V2zpOJmFXl0KBsAsNxmlckoZjKMXGY8UnF0ac7NWAaeUhlzCuDNnAg8XaLI8xsZ9UX4ivintFZVHlsQT1dQ9IzpKA2SMaOMy6qQhWqOleDsJY04S7/hPVoQqoTkB+Y+CpE2ayZZEsIRoiQIZcGTXME8fZFXzAXeHudTFX/dIRUjrWHWQJc3mSIkYT/PaUFiOztj3DbCEm+J+JV7flJD3Tq6dLfVI0eFXVII5ev+yhdyvVQx6xaVkn5nlABwogTANiUAXEoCrE4CakkABFcmAf1OAk6WAHiiBNit7gLqIFoDQ2/NXyMOWIfBuT5oPqrOuusjI5F66qi2YSmq+6Vwjdele2UADzlHu1yzpWqwOjKP7RTncUt78XJ74B5rLx/iFWRsS31Sn4DwUjkIdDmoVg6yry0HDbocdLLQ2ScKndNqDqqDaCGh1AE0BSfD4ylfdwCchAgZ+E85WuwnQguAniVzvTfhOKWEA3pvJJzj7ZtJOPalEg7sEk6thONcW8Jx9jCmgyuBq1fezbYNl2VV4bnABqH9ZJ+cF76ZHA4AeqFsbzYvwOYMecUO4yi4gDlFoUxg5rdpVa+n0m/iI5otY0gUSREHail6Z4TSkqkSlyoiiYfoUFcsiO/TQ/JS5O4ZQnpQjGhgViPa3RPRsLGIbuCgEppnoIx6rY4wkiH9AycaOcbAPYwBjTGmgWOFszDmU8cXxYUKX9yW+dLAV0GnMGdkjDO4NoVxr5QxncJERwvXpjCggW2vZe87dzAmjtF3jFFPPQwnRh9GD3fGwDUmrjEcG8NexxHFEbPEEee0fW5zHGngNzkdRz7GkV7pW8humyMNfAvtP7+0u/PLmgdipWvXgVOhjL2HMnZjlIFVeC55vwLswg2LeWu60HjjlkWVHjEn0gMKl7auUT7624yzXKO8dW/vQHCsfTPXKOBav5i6/W/MoX6JE3ZT+19ZzH4vHtMr+00+nPwH -------------------------------------------------------------------------------- /document/src/递归下降.drawio: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | #include "string.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | using namespace std; 11 | 12 | 13 | /* logo 14 | 0123456789012345678901234567890123 15 | ###### ##### ##### 16 | ## ### ## ### ## 17 | ## ## ## 18 | ## ## ## 19 | ## ## ## 20 | ## ## ## 21 | ## ## ### ## ### ## 22 | #### ###### ###### 23 | */ 24 | 25 | // 26 | // aux routines for colorful printf. And you should not pay more attention to them 27 | // 28 | #define xINFO(_X_,...) color_printf(FG_WHITE,_X_,__VA_ARGS__) 29 | 30 | #define xPANIC(_X_,...) color_printf(FG_RED,_X_,__VA_ARGS__) 31 | 32 | #define xSUCC(_X_,...) color_printf(FG_GREEN,_X_,__VA_ARGS__) 33 | 34 | #define xWARN(_X_,...) color_printf(FG_YELLOW,_X_,__VA_ARGS__) 35 | 36 | 37 | #define FG_BLACK 0x00 38 | #define FG_BLUE 0x01 39 | #define FG_GREEN 0x02 40 | #define FG_BLUE_2 0x03 41 | #define FG_RED 0x04 42 | #define FG_PURPLE 0x05 43 | #define FG_YELLOW 0x06 44 | #define FG_WHITE 0x0F 45 | 46 | inline void setColor(int color, const bool bIntensity = true) { 47 | SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color | (bIntensity ? FOREGROUND_INTENSITY : 0)); 48 | } 49 | 50 | inline void resetColor() { 51 | setColor(FG_WHITE); 52 | } 53 | 54 | inline int color_printf(const int color, const char* pszFmt, ...) { 55 | if (color != -1) { 56 | setColor(color); 57 | } 58 | va_list marker; 59 | va_start(marker, pszFmt); 60 | auto ri = vprintf(pszFmt, marker); 61 | va_end(marker); 62 | resetColor(); 63 | return ri; 64 | } 65 | 66 | void Usage() { 67 | color_printf(FG_PURPLE,"%s", "jcc file1 file2 ...\n"); 68 | xINFO("%s", " [-h] help show detail information\n"); 69 | xINFO("%s", " [-v] show verision and developer info\n"); 70 | xINFO("%s", " [-c] compile the c code to s code\n"); 71 | xINFO("%s", " [-s] assmble the s code to obj code(elf-x86)\n"); 72 | xINFO("%s", " [-l][out_name] link the obj file to one elf file\n"); 73 | xINFO("%s", " [-o][out_name] compile the c code to elf file\n"); 74 | } 75 | 76 | 77 | void Printc(char c = '#') { 78 | xINFO("%s", "\nWelcome to JCC tools!\n"); 79 | xINFO("%s", "jcc means Just Compiler Compiler, which similar to gcc homophonic.\n"); 80 | xINFO("%s", "if you have any question,pls contact with djh113@126.com\n"); 81 | xWARN("%s", "version 1.0 ...\n\n\n"); 82 | char position[][33] = { { 0,1,2,3,4,5,12,13,14,15,16,17,27,28,29,30,31}, 83 | {4,5,12,13,14,17,18,26,27,28,31,32}, 84 | {4,5,11,12,25,26,}, 85 | {4,5,11,12,25,26,}, 86 | {4,5,11,12,25,26,}, 87 | {4,5,11,12,25,26,}, 88 | {0,1,4,5,12,13,14,18,19,26,27,28,32,33}, 89 | {1,2,3,4,13,14,15,16,17,18,27,28,29,30,31,32}, 90 | }; 91 | for (int i = 0; i < 8; i++) { 92 | int suffix = 10; 93 | while (suffix--) putchar(' '); 94 | char count = -1; 95 | for (int k = 0; k < 33; k++) { 96 | char element = position[i][k] - count - 1; 97 | count = position[i][k]; 98 | if (element >= 0) { 99 | while (element) { 100 | putchar(' '); 101 | element--; 102 | } 103 | xSUCC("%c", c); 104 | } 105 | else break; 106 | } 107 | putchar('\n'); 108 | } 109 | resetColor(); 110 | putchar('\n'); 111 | Usage(); 112 | } 113 | 114 | 115 | void Compile(string pwd,vector&files) { 116 | string cmd = ""; 117 | for (int i = 0; i < files.size(); i++) { 118 | cmd += files[i]; 119 | cmd += " "; 120 | } 121 | cmd = "jcc " + cmd; 122 | cmd = pwd + "\\Compiler\\compile.exe " + cmd; 123 | system(cmd.c_str()); 124 | } 125 | 126 | void Assemble(string pwd, vector& files) { 127 | string cmd = ""; 128 | for (int i = 0; i < files.size(); i++) { 129 | cmd += files[i]; 130 | cmd += " "; 131 | } 132 | cmd = "ass " + cmd; 133 | cmd = pwd + "\\Assembler\\assembly.exe " + cmd; 134 | system(cmd.c_str()); 135 | } 136 | 137 | void Linker(string pwd,vector&files,string output_path="") { 138 | string cmd = ""; 139 | for (int i = 0; i < files.size(); i++) { 140 | cmd += files[i]; 141 | cmd += " "; 142 | } 143 | cmd = "link " + cmd; 144 | cmd = pwd + "\\Linker\\linker.exe " + cmd; 145 | if (output_path != "") { 146 | cmd = cmd + " -o " + output_path; 147 | } 148 | system(cmd.c_str()); 149 | } 150 | 151 | int main(int argc, char* argv[]) { 152 | if (argc < 2) { 153 | Printc(); 154 | } 155 | else if (strcmpi(argv[1], "jcc") == 0) { 156 | int i = 2; 157 | vectorfile_names; 158 | file_names.clear(); 159 | // getting current work dir 160 | string pwd = getcwd(nullptr, 0); 161 | string output_path = ""; 162 | char option = 0; 163 | for (i; i < argc; i++) { 164 | if (argv[i][0] == '-') { 165 | option = strlen(argv[i]) <= 1 ? 0 : argv[i][1]; 166 | i++; 167 | break; 168 | } 169 | else { 170 | file_names.push_back(argv[i]); 171 | } 172 | } 173 | // check valid 174 | if (option == 0) { 175 | xPANIC("%s", "missing parameter! -?\n"); 176 | return 0; 177 | } 178 | else if (file_names.size() == 0 && option != 'h' && option != 'v') { 179 | xWARN("%s", "no input file!\n"); 180 | } 181 | else if (i < argc) { 182 | if (i == argc - 1) { 183 | output_path = argv[i]; 184 | } 185 | else { 186 | xWARN("%s", "more parameter given!\n"); 187 | } 188 | } 189 | // parameter parser 190 | switch (option) { 191 | case 'h': { 192 | Usage(); 193 | break; 194 | } 195 | case 'v': { 196 | Printc(); 197 | break; 198 | } 199 | case 'c': { 200 | Compile(pwd, file_names); 201 | break; 202 | } 203 | case 's': { 204 | Assemble(pwd, file_names); 205 | break; 206 | } 207 | case 'l': { 208 | Linker(pwd, file_names, output_path); 209 | break; 210 | } 211 | case 'o': { 212 | Compile(pwd, file_names); 213 | for (int i = 0; i < file_names.size(); i++) { 214 | int index = file_names[i].find_last_of('.'); 215 | file_names[i] = file_names[i].substr(0, index) + ".s"; 216 | } 217 | int index = file_names[0].find_last_of('\\'); 218 | if (index == string::npos) { 219 | index = file_names[0].find_last_of('/'); 220 | } 221 | string common_file = file_names[0].substr(0, index) + "\\common.s"; 222 | file_names.push_back(common_file); 223 | Assemble(pwd, file_names); 224 | for (int i = 0; i < file_names.size(); i++) { 225 | file_names[i] = file_names[i] + ".o"; 226 | } 227 | Linker(pwd, file_names, output_path); 228 | break; 229 | } 230 | } 231 | } 232 | else { 233 | xPANIC("Not recognize command %s ,using jcc\n", argv[1]); 234 | Printc(); 235 | } 236 | return 0; 237 | } 238 | 239 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | .\make_tool\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 -------------------------------------------------------------------------------- /make_tool/README.md: -------------------------------------------------------------------------------- 1 | # 这只是一个Make工具 2 | 3 | -------------------------------------------------------------------------------- /make_tool/make.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/make_tool/make.exe -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @cd ./compiler 2 | @echo updating cc ... 3 | @call make 4 | @echo update cc succefully! 5 | @cd .. 6 | @cd ./Assembler 7 | @echo updating ass 8 | @call make 9 | @echo update ass successfully! 10 | @cd .. 11 | @cd ./Linker 12 | @echo updating linker 13 | @call make 14 | @echo update linker successfully! 15 | @cd .. 16 | @echo updating main-control 17 | @call make 18 | @echo update over! -------------------------------------------------------------------------------- /test/common.s: -------------------------------------------------------------------------------- 1 | section .text 2 | @str2long: 3 | mov edx,@str2long_data_len 4 | mov ecx,@str2long_data 5 | mov ebx,1 6 | mov eax,4 7 | int 128 8 | mov ebx,0 9 | mov eax,1 10 | int 128 11 | ret 12 | @procBuf: 13 | mov esi,@buffer 14 | mov edi,0 15 | mov ecx,0 16 | mov eax,0 17 | mov ebx,10 18 | @cal_buf_len: 19 | mov cl,[esi+edi] 20 | cmp ecx,10 21 | je @cal_buf_len_exit 22 | inc edi 23 | imul ebx 24 | add eax,ecx 25 | sub eax,48 26 | jmp @cal_buf_len 27 | @cal_buf_len_exit: 28 | mov ecx,edi 29 | mov [@buffer_len],cl 30 | mov bl,[esi] 31 | ret 32 | global _start 33 | _start: 34 | call main 35 | mov ebx,0 36 | mov eax,1 37 | int 128 38 | ret 39 | section .data 40 | @str2long_data db "Str-Overflow",10,13 41 | @str2long_data_len equ 14 42 | @buffer times 255 db 0 43 | @buffer_len db 0 44 | @s_esp dd @s_base 45 | @s_ebp dd 0 46 | section .bss 47 | @s_stack times 65536 db 0 48 | @s_base: 49 | -------------------------------------------------------------------------------- /test/common.s.t: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/test/common.s.t -------------------------------------------------------------------------------- /test/test.s: -------------------------------------------------------------------------------- 1 | section .text 2 | Fibonacci: 3 | push ebp 4 | mov ebp,esp 5 | mov ebx,[@s_esp] 6 | mov [@s_esp],esp 7 | mov esp,ebx 8 | mov ebx,[@s_ebp] 9 | push ebx 10 | mov [@s_ebp],esp 11 | mov ebx,[@s_esp] 12 | mov [@s_esp],esp 13 | mov esp,ebx 14 | push 1 15 | push 0 16 | mov eax,[ebp+8] 17 | mov ebx,[ebp-4] 18 | cmp eax,ebx 19 | je @lab_base_cmp_3 20 | mov eax,0 21 | jmp @lab_base_cmp_exit_4 22 | @lab_base_cmp_3: 23 | mov eax,1 24 | @lab_base_cmp_exit_4: 25 | mov [ebp-8],eax 26 | push 0 27 | push 0 28 | mov eax,[ebp+8] 29 | mov ebx,[ebp-12] 30 | cmp eax,ebx 31 | je @lab_base_cmp_7 32 | mov eax,0 33 | jmp @lab_base_cmp_exit_8 34 | @lab_base_cmp_7: 35 | mov eax,1 36 | @lab_base_cmp_exit_8: 37 | mov [ebp-16],eax 38 | push 0 39 | mov eax,[ebp-8] 40 | mov ebx,[ebp-16] 41 | or eax,ebx 42 | jne @lab_base_cmp_10 43 | mov eax,0 44 | jmp @lab_base_cmp_exit_11 45 | @lab_base_cmp_10: 46 | mov eax,1 47 | @lab_base_cmp_exit_11: 48 | mov [ebp-20],eax 49 | mov eax,[ebp-20] 50 | cmp eax,0 51 | je @if_1_middle 52 | push 1 53 | mov eax,[ebp-24] 54 | mov ebx,[@s_ebp] 55 | mov [@s_esp],ebx 56 | mov ebx,[@s_esp] 57 | mov [@s_esp],esp 58 | mov esp,ebx 59 | pop ebx 60 | mov [@s_ebp],ebx 61 | mov ebx,[@s_esp] 62 | mov [@s_esp],esp 63 | mov esp,ebx 64 | mov esp,ebp 65 | pop ebp 66 | ret 67 | mov esp,ebp 68 | jmp @if_1_end 69 | @if_1_middle: 70 | mov esp,ebp 71 | push 1 72 | push 0 73 | mov eax,[ebp+8] 74 | mov ebx,[ebp-4] 75 | sub eax,ebx 76 | mov [ebp-8],eax 77 | mov eax,[ebp-8] 78 | push eax 79 | call Fibonacci 80 | add esp,4 81 | push 0 82 | mov [ebp-12],eax 83 | push 2 84 | push 0 85 | mov eax,[ebp+8] 86 | mov ebx,[ebp-16] 87 | sub eax,ebx 88 | mov [ebp-20],eax 89 | mov eax,[ebp-20] 90 | push eax 91 | call Fibonacci 92 | add esp,4 93 | push 0 94 | mov [ebp-24],eax 95 | push 0 96 | mov eax,[ebp-12] 97 | mov ebx,[ebp-24] 98 | add eax,ebx 99 | mov [ebp-28],eax 100 | mov eax,[ebp-28] 101 | mov ebx,[@s_ebp] 102 | mov [@s_esp],ebx 103 | mov ebx,[@s_esp] 104 | mov [@s_esp],esp 105 | mov esp,ebx 106 | pop ebx 107 | mov [@s_ebp],ebx 108 | mov ebx,[@s_esp] 109 | mov [@s_esp],esp 110 | mov esp,ebx 111 | mov esp,ebp 112 | pop ebp 113 | ret 114 | mov esp,ebp 115 | @if_1_end: 116 | mov esp,ebp 117 | mov ebx,[@s_ebp] 118 | mov [@s_esp],ebx 119 | mov ebx,[@s_esp] 120 | mov [@s_esp],esp 121 | mov esp,ebx 122 | pop ebx 123 | mov [@s_ebp],ebx 124 | mov ebx,[@s_esp] 125 | mov [@s_esp],esp 126 | mov esp,ebx 127 | mov esp,ebp 128 | pop ebp 129 | ret 130 | main: 131 | push ebp 132 | mov ebp,esp 133 | mov ebx,[@s_esp] 134 | mov [@s_esp],esp 135 | mov esp,ebx 136 | mov ebx,[@s_ebp] 137 | push ebx 138 | mov [@s_ebp],esp 139 | mov ebx,[@s_esp] 140 | mov [@s_esp],esp 141 | mov esp,ebx 142 | @for_1_start: 143 | push 0 144 | push 1 145 | lea eax,[ebp-4] 146 | mov ebx,[ebp-8] 147 | mov [eax],ebx 148 | @for_1_loop: 149 | push 20 150 | push 0 151 | mov eax,[ebp-4] 152 | mov ebx,[ebp-12] 153 | cmp eax,ebx 154 | jl @lab_base_cmp_23 155 | mov eax,0 156 | jmp @lab_base_cmp_exit_24 157 | @lab_base_cmp_23: 158 | mov eax,1 159 | @lab_base_cmp_exit_24: 160 | mov [ebp-16],eax 161 | mov eax,[ebp-16] 162 | cmp eax,0 163 | je @for_1_exit 164 | push 1 165 | push 0 166 | jmp @for_1_blcok 167 | @for_1_iter: 168 | mov eax,[ebp-4] 169 | mov ebx,[ebp-20] 170 | add eax,ebx 171 | mov [ebp-24],eax 172 | lea eax,[ebp-4] 173 | mov ebx,[ebp-24] 174 | mov [eax],ebx 175 | lea esp,[ebp-8] 176 | jmp @for_1_loop 177 | @for_1_blcok: 178 | push 1 179 | push 2 180 | mov eax,[ebp-4] 181 | push eax 182 | call Fibonacci 183 | add esp,4 184 | push 0 185 | mov [ebp-36],eax 186 | push 3 187 | push -1 188 | mov eax,[@s_esp] 189 | mov [@s_esp],esp 190 | mov esp,eax 191 | mov eax,@str_3_len 192 | sub esp,1 193 | mov [esp],al 194 | mov [ebp-44],esp 195 | cmp eax,0 196 | je @lab_cpystr2_exit_33 197 | mov ecx,@str_3_len 198 | dec ecx 199 | mov esi,@str_3 200 | @lab_cpystr2_32: 201 | cmp ecx,-1 202 | je @lab_cpystr2_exit_33 203 | mov dl,[esi+ecx] 204 | sub esp,1 205 | mov [esp],dl 206 | dec ecx 207 | jmp @lab_cpystr2_32 208 | @lab_cpystr2_exit_33: 209 | mov eax,[@s_esp] 210 | mov [@s_esp],esp 211 | mov esp,eax 212 | mov eax,[@s_esp] 213 | mov [@s_esp],esp 214 | mov esp,eax 215 | mov eax,[ebp-36] 216 | mov esi,[ebp-44] 217 | mov edi,0 218 | cmp eax,0 219 | jge @lab_numsign1_exit_37 220 | @lab_numsign1_36: 221 | neg eax 222 | mov edi,1 223 | @lab_numsign1_exit_37: 224 | mov ebx,10 225 | @lab_num2str1_34: 226 | mov edx,0 227 | idiv ebx 228 | mov cl,[esi] 229 | inc cl 230 | mov [esi],cl 231 | sub esp,1 232 | add dl,48 233 | mov [esp],dl 234 | cmp eax,0 235 | jne @lab_num2str1_34 236 | cmp edi,0 237 | je @lab_numsign_add_38 238 | sub esp,1 239 | mov ecx,45 240 | mov [esp],cl 241 | mov cl,[esi] 242 | inc cl 243 | mov [esi],cl 244 | @lab_numsign_add_38: 245 | cmp cl,255 246 | jna @lab_num2str1_exit_35 247 | call @str2long 248 | @lab_num2str1_exit_35: 249 | mov eax,[@s_esp] 250 | mov [@s_esp],esp 251 | mov esp,eax 252 | push -1 253 | mov eax,[@s_esp] 254 | mov [@s_esp],esp 255 | mov esp,eax 256 | mov ebx,[ebp-44] 257 | mov eax,0 258 | mov al,[ebx] 259 | sub esp,1 260 | mov [esp],al 261 | mov [ebp-48],esp 262 | cmp eax,0 263 | je @lab_cpystr2_exit_41 264 | mov ecx,0 265 | mov esi,ebx 266 | dec esi 267 | neg eax 268 | @lab_cpystr2_40: 269 | cmp ecx,eax 270 | je @lab_cpystr2_exit_41 271 | mov dl,[esi+ecx] 272 | sub esp,1 273 | mov [esp],dl 274 | dec ecx 275 | jmp @lab_cpystr2_40 276 | @lab_cpystr2_exit_41: 277 | mov eax,[@s_esp] 278 | mov [@s_esp],esp 279 | mov esp,eax 280 | mov eax,[@s_esp] 281 | mov [@s_esp],esp 282 | mov esp,eax 283 | mov eax,@str_2_len 284 | cmp eax,0 285 | je @lab_cpystr1_exit_43 286 | mov ebx,[ebp-48] 287 | mov edx,0 288 | mov dl,[ebx] 289 | add edx,eax 290 | mov [ebx],dl 291 | mov ecx,@str_2_len 292 | dec ecx 293 | mov esi,@str_2 294 | cmp edx,255 295 | jna @lab_cpystr1_42 296 | call @str2long 297 | @lab_cpystr1_42: 298 | cmp ecx,-1 299 | je @lab_cpystr1_exit_43 300 | mov al,[esi+ecx] 301 | sub esp,1 302 | mov [esp],al 303 | dec ecx 304 | jmp @lab_cpystr1_42 305 | @lab_cpystr1_exit_43: 306 | mov eax,[@s_esp] 307 | mov [@s_esp],esp 308 | mov esp,eax 309 | push -1 310 | mov eax,[@s_esp] 311 | mov [@s_esp],esp 312 | mov esp,eax 313 | mov ebx,[ebp-48] 314 | mov eax,0 315 | mov al,[ebx] 316 | sub esp,1 317 | mov [esp],al 318 | mov [ebp-52],esp 319 | cmp eax,0 320 | je @lab_cpystr2_exit_46 321 | mov ecx,0 322 | mov esi,ebx 323 | dec esi 324 | neg eax 325 | @lab_cpystr2_45: 326 | cmp ecx,eax 327 | je @lab_cpystr2_exit_46 328 | mov dl,[esi+ecx] 329 | sub esp,1 330 | mov [esp],dl 331 | dec ecx 332 | jmp @lab_cpystr2_45 333 | @lab_cpystr2_exit_46: 334 | mov eax,[@s_esp] 335 | mov [@s_esp],esp 336 | mov esp,eax 337 | mov eax,[@s_esp] 338 | mov [@s_esp],esp 339 | mov esp,eax 340 | mov eax,[ebp-4] 341 | mov esi,[ebp-52] 342 | mov edi,0 343 | cmp eax,0 344 | jge @lab_numsign1_exit_50 345 | @lab_numsign1_49: 346 | neg eax 347 | mov edi,1 348 | @lab_numsign1_exit_50: 349 | mov ebx,10 350 | @lab_num2str1_47: 351 | mov edx,0 352 | idiv ebx 353 | mov cl,[esi] 354 | inc cl 355 | mov [esi],cl 356 | sub esp,1 357 | add dl,48 358 | mov [esp],dl 359 | cmp eax,0 360 | jne @lab_num2str1_47 361 | cmp edi,0 362 | je @lab_numsign_add_51 363 | sub esp,1 364 | mov ecx,45 365 | mov [esp],cl 366 | mov cl,[esi] 367 | inc cl 368 | mov [esi],cl 369 | @lab_numsign_add_51: 370 | cmp cl,255 371 | jna @lab_num2str1_exit_48 372 | call @str2long 373 | @lab_num2str1_exit_48: 374 | mov eax,[@s_esp] 375 | mov [@s_esp],esp 376 | mov esp,eax 377 | push -1 378 | mov eax,[@s_esp] 379 | mov [@s_esp],esp 380 | mov esp,eax 381 | mov ebx,[ebp-52] 382 | mov eax,0 383 | mov al,[ebx] 384 | sub esp,1 385 | mov [esp],al 386 | mov [ebp-56],esp 387 | cmp eax,0 388 | je @lab_cpystr2_exit_54 389 | mov ecx,0 390 | mov esi,ebx 391 | dec esi 392 | neg eax 393 | @lab_cpystr2_53: 394 | cmp ecx,eax 395 | je @lab_cpystr2_exit_54 396 | mov dl,[esi+ecx] 397 | sub esp,1 398 | mov [esp],dl 399 | dec ecx 400 | jmp @lab_cpystr2_53 401 | @lab_cpystr2_exit_54: 402 | mov eax,[@s_esp] 403 | mov [@s_esp],esp 404 | mov esp,eax 405 | mov eax,[@s_esp] 406 | mov [@s_esp],esp 407 | mov esp,eax 408 | mov eax,@str_1_len 409 | cmp eax,0 410 | je @lab_cpystr1_exit_56 411 | mov ebx,[ebp-56] 412 | mov edx,0 413 | mov dl,[ebx] 414 | add edx,eax 415 | mov [ebx],dl 416 | mov ecx,@str_1_len 417 | dec ecx 418 | mov esi,@str_1 419 | cmp edx,255 420 | jna @lab_cpystr1_55 421 | call @str2long 422 | @lab_cpystr1_55: 423 | cmp ecx,-1 424 | je @lab_cpystr1_exit_56 425 | mov al,[esi+ecx] 426 | sub esp,1 427 | mov [esp],al 428 | dec ecx 429 | jmp @lab_cpystr1_55 430 | @lab_cpystr1_exit_56: 431 | mov eax,[@s_esp] 432 | mov [@s_esp],esp 433 | mov esp,eax 434 | push -1 435 | mov eax,[@s_esp] 436 | mov [@s_esp],esp 437 | mov esp,eax 438 | mov ebx,[ebp-56] 439 | mov eax,0 440 | mov al,[ebx] 441 | sub esp,1 442 | mov [esp],al 443 | mov [ebp-60],esp 444 | cmp eax,0 445 | je @lab_cpystr2_exit_59 446 | mov ecx,0 447 | mov esi,ebx 448 | dec esi 449 | neg eax 450 | @lab_cpystr2_58: 451 | cmp ecx,eax 452 | je @lab_cpystr2_exit_59 453 | mov dl,[esi+ecx] 454 | sub esp,1 455 | mov [esp],dl 456 | dec ecx 457 | jmp @lab_cpystr2_58 458 | @lab_cpystr2_exit_59: 459 | mov eax,[@s_esp] 460 | mov [@s_esp],esp 461 | mov esp,eax 462 | mov ecx,[ebp-60] 463 | mov edx,0 464 | mov dl,[ecx] 465 | sub ecx,edx 466 | mov ebx,1 467 | mov eax,4 468 | int 128 469 | jmp @for_1_iter 470 | @for_1_exit: 471 | mov esp,ebp 472 | push 0 473 | mov eax,[ebp-4] 474 | mov ebx,[@s_ebp] 475 | mov [@s_esp],ebx 476 | mov ebx,[@s_esp] 477 | mov [@s_esp],esp 478 | mov esp,ebx 479 | pop ebx 480 | mov [@s_ebp],ebx 481 | mov ebx,[@s_esp] 482 | mov [@s_esp],esp 483 | mov esp,ebx 484 | mov esp,ebp 485 | pop ebp 486 | ret 487 | section .data 488 | @str_1 db "fib(" 489 | @str_1_len equ 4 490 | @str_2 db "):" 491 | @str_2_len equ 2 492 | @str_3 db 10 493 | @str_3_len equ 1 494 | section .bss 495 | -------------------------------------------------------------------------------- /test/test.s.t: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djh-sudo/tiny-C-Compiler/212133151f3c06b3e3911d15ee129a93a5029bf1/test/test.s.t -------------------------------------------------------------------------------- /test/test.tc: -------------------------------------------------------------------------------- 1 | int Fibonacci(int k){ 2 | if(k == 1 || k == 0){ 3 | return 1; 4 | }else{ 5 | return Fibonacci(k - 1) + Fibonacci(k - 2); 6 | } 7 | } 8 | 9 | int main(){ 10 | for(int i=1;i<20;i=i+1){ 11 | out << "fib(" + i + "):" + Fibonacci(i) + "\n"; 12 | } 13 | return 0; 14 | } --------------------------------------------------------------------------------