bool retf(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes, List <AsmParser.ParseOutput> parameters, AssemblerState state) { ret.Add(new CodeBlock { Code = new byte[] { 0xcb } }); return(true); }
private OpcodeImplementation.OpcodeDelegate FindOperation(AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes, List <AsmParser.ParseOutput> parameters, AssemblerState state) { if (!opcodes.ContainsKey(op.Name)) { return(null); } List <OpcodeImplementation> ops = opcodes[op.Name]; if (ops == null) { return(null); } foreach (OpcodeImplementation oi in ops) { // Match prefixes bool allowed = true; foreach (AsmParser.ParseOutput prefix in prefixes) { if (!oi.AllowedPrefixes.Contains(prefix.Name.ToLower())) { allowed = false; break; } } if (!allowed) { continue; } // Match parameters if (parameters.Count != oi.ParamConstraints.Count) { continue; } for (int i = 0; i < parameters.Count; i++) { Location l = ParseLocation(parameters[i]); if (!MatchConstraint(oi.ParamConstraints[i], l)) { allowed = false; break; } } if (!allowed) { continue; } return(oi.emitter); } return(null); }
bool mov_r3264_creg(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes, List <AsmParser.ParseOutput> parameters, AssemblerState state) { Reg r = regs[parameters[1].Name]; Reg rm = regs[parameters[0].Name]; AppendRex(ret, GenerateRex(false, r, rm)); ret.Add(new CodeBlock { Code = new byte[] { 0x0f, 0x20 } }); AppendModRM(ret, r, rm, state); return(true); }
private void AssembleLabel(AsmParser.ParseOutput line_entry, AssemblerState state) { Label l = new Label { Name = line_entry.Name, ObjectType = binary_library.SymbolObjectType.Unknown, Type = binary_library.SymbolType.Local }; if (state.sym_types.ContainsKey(line_entry.Name)) { l.Type = state.sym_types[line_entry.Name]; } if (state.sym_obj_types.ContainsKey(line_entry.Name)) { l.ObjectType = state.sym_obj_types[line_entry.Name]; } state.OutputBlocks.Add(l); }
private void AssembleOperation(AsmParser.ParseOutput line_entry, AssemblerState state) { // Interpret the operation List <AsmParser.ParseOutput> prefixes = new List <AsmParser.ParseOutput>(); AsmParser.ParseOutput op = null; List <AsmParser.ParseOutput> parameters = new List <AsmParser.ParseOutput>(); foreach (AsmParser.ParseOutput p in line_entry.Children) { switch (p.Type) { case AsmParser.ParseOutput.OutputType.Operation: if (op != null) { throw new Exception("More than one operation per line"); } op = p; break; case AsmParser.ParseOutput.OutputType.Prefix: prefixes.Add(p); break; case AsmParser.ParseOutput.OutputType.Parameter: if (p.Children.Count > 1) { throw new Exception("Only one parameter child allowed"); } parameters.Add(p.Children[0]); break; default: throw new Exception("Unsupported operation argument type: " + p.ToString()); } } // Now get the appropriate operations OpcodeImplementation.OpcodeDelegate del = FindOperation(op, prefixes, parameters, state); if ((del == null) || (!del(state.OutputBlocks, op, prefixes, parameters, state))) { throw new Exception("Unable to assemble: " + line_entry.ToString()); } }
static void Main(string[] args) { // Load a test file string test_file = "..\\..\\..\\libsupcs\\x86_64_cpu.asm"; FileStream fs = new FileStream(test_file, FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); string file = sr.ReadToEnd(); // Tokenize and parse List <Tokenizer.TokenDefinition> tokens = Tokenizer.Tokenize(file, Tokenizer.CAsmTokenGrammar, Tokenizer.NasmPreprocessorOptions); AsmParser.ParseOutput parsed = AsmParser.Parse(tokens); // Create an output file binary_library.IBinaryFile output_file = binary_library.BinaryFile.CreateBinaryFile("elf"); // Assemble to the output file Assembler ass = new x86_Assembler(); ass.Assemble(parsed, output_file); }
public void Assemble(AsmParser.ParseOutput input, binary_library.IBinaryFile output) { AssemblerState state = CreateAssemblerState(output); if (input.Type != AsmParser.ParseOutput.OutputType.Block) { throw new Exception("Expected Block"); } foreach (AsmParser.ParseOutput line in input.Children) { if (line.Type != AsmParser.ParseOutput.OutputType.Line) { throw new Exception("Expected Line"); } foreach (AsmParser.ParseOutput line_entry in line.Children) { switch (line_entry.Type) { case AsmParser.ParseOutput.OutputType.DirectiveCommand: AssembleDirective(line_entry, state); break; case AsmParser.ParseOutput.OutputType.OpCommand: AssembleOperation(line_entry, state); break; case AsmParser.ParseOutput.OutputType.Label: AssembleLabel(line_entry, state); break; default: throw new NotSupportedException(); } } } }
private void AssembleDirective(AsmParser.ParseOutput line_entry, AssemblerState state) { AsmParser.ParseOutput dir = line_entry.Children[0]; // Interpret directives if ((dir.Name == "weak") || (dir.Name == "global")) { // these are of the form <weak | global> <label> [:function | :data] string t_name = line_entry.Children[1].Children[0].Name; binary_library.SymbolType st = binary_library.SymbolType.Undefined; binary_library.SymbolObjectType sot = binary_library.SymbolObjectType.Unknown; if (dir.Name == "weak") { st = binary_library.SymbolType.Weak; } else if (dir.Name == "global") { st = binary_library.SymbolType.Global; } if (line_entry.Children.Count >= 3) { string ot_name = line_entry.Children[2].Children[0].Name; if (ot_name == "function") { sot = binary_library.SymbolObjectType.Function; } else if (ot_name == "data") { sot = binary_library.SymbolObjectType.Object; } } if (st != binary_library.SymbolType.Undefined) { state.sym_types[t_name] = st; } if (sot != binary_library.SymbolObjectType.Unknown) { state.sym_obj_types[t_name] = sot; } } else if (dir.Name == "extern") { string t_name = line_entry.Children[1].Name; if (!state.extern_labels.Contains(t_name)) { state.extern_labels.Add(t_name); } } else if (dir.Name == "bits16") { state.cur_bitness = binary_library.Bitness.Bits16; } else if (dir.Name == "bits32") { state.cur_bitness = binary_library.Bitness.Bits32; } else if (dir.Name == "bits64") { state.cur_bitness = binary_library.Bitness.Bits64; } else { throw new NotImplementedException(); } }
protected virtual Location ParseLocation(AsmParser.ParseOutput param) { switch (param.Type) { case AsmParser.ParseOutput.OutputType.Label: return(new Location { AType = Location.LocationType.Label, A = param.Name }); case AsmParser.ParseOutput.OutputType.Number: return(new Location { AType = Location.LocationType.Number, A = param.Name }); case AsmParser.ParseOutput.OutputType.Register: return(new Location { AType = Location.LocationType.Register, A = param.Name }); case AsmParser.ParseOutput.OutputType.ContentsOf: AsmParser.ParseOutput p = param.Children[0]; if (p.Type != AsmParser.ParseOutput.OutputType.Parameter) { throw new NotSupportedException(); } AsmParser.ParseOutput e = p.Children[0]; if (e.Type != AsmParser.ParseOutput.OutputType.Expression) { throw new NotSupportedException(); } Location l = ParseLocation(e.Children[0]); l.ModifierType = Location.LocationModifierType.ContentsOf; if (e.Children.Count > 1) { if (e.Children[1].Type != AsmParser.ParseOutput.OutputType.NumOp) { throw new NotSupportedException(); } AsmParser.ParseOutput nop = e.Children[1]; if (nop.Name == "+") { l.NumOp = Location.NumOpType.Plus; } else if (nop.Name == "-") { l.NumOp = Location.NumOpType.Minus; } else { throw new NotSupportedException(); } Location b = ParseLocation(e.Children[2]); l.BType = b.AType; l.B = b.A; } return(l); default: throw new NotSupportedException(); } }
bool mov_creg_r3264(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes, List <AsmParser.ParseOutput> parameters, AssemblerState state) { return(true); }