public bool WriteAsm(StreamWriter sw, MethodData md) { bool ok = true; string name = md.FullName; sw.WriteLine("; {0}", name); sw.WriteLine("{0}:", Util.MangleFunction(md)); ArrayList list = new ArrayList(); if (md.LocalVars != null || md.ParamCount > 0) { list.Add(new X86Code("push", "bp")); list.Add(new X86Code("mov", "bp", "sp")); if (md.LocalVars != null) { list.Add(new X86Code("sub", "sp", (md.LocalVars.Count * 2).ToString())); } } foreach (object obj in ConvertNative(md)) { X86Codes codes = obj as X86Codes; if (codes == null) { ILCode il = obj as ILCode; codes = ConvertIL(md, il); if (codes == null) { ok = false; Console.WriteLine("ERROR PE_{0:X8}: {1} in {2}", il.Address, il.OpCode, md.FullName); continue; } } codes.Output(list); } switch (this.optimize) { case 1: X86Code.Optimize(list); break; case 2: this.Optimize(list, md); break; } foreach (object obj in list) { X86Code x = obj as X86Code; x.Write(sw); } return(ok); }
public void Output(ArrayList list) { bool first = true; foreach (object obj in this.Codes) { X86Code x = obj as X86Code; if (first) { x.Label = string.Format("PE_{0:X8}", this.Address); x.IsBrTarget = this.IsBrTarget; if (this.Comment != "") { x.Comment = this.Comment; } first = false; } list.Add(x); } }
public static X86Code GetPrevious(ArrayList list, int pos, int count) { if (pos <= 0 || pos >= list.Count) { return(null); } for (int i = pos - 1; i >= 0; i--) { X86Code x = list[i] as X86Code; if (x != null && !x.ignore && (--count) < 1) { return(x); } if (x.IsBrTarget || x.Mnemonic == "call") { break; } } return(null); }
public static void Optimize(ArrayList list) { for (int i = 1; i < list.Count; i++) { X86Code x0 = list[i] as X86Code; if (x0 == null || x0.ignore || x0.IsBrTarget) { continue; } ArrayList listx = new ArrayList(); listx.Add(x0); for (int j = 1;; j++) { X86Code xx = GetPrevious(list, i, j); if (xx == null) { break; } listx.Add(xx); } if (listx.Count < 2) { continue; } X86Code[] x = listx.ToArray(typeof(X86Code)) as X86Code[]; if (IsMovEtc(x[0].Mnemonic) && !IsXS(x[0].Operand1) && IsXX(x[0].Operand2) && x[0].Operand1 != x[0].Operand2) { for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[0].Operand2 && !IsXS(x[j].Operand2) && !(IsAddr(x[0].Operand1) && IsAddr(x[j].Operand2))) { if (x[0].Operand1 != x[j].Operand2 && (IsXX(x[0].Operand1) || IsXX(x[j].Operand2))) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[0].Mnemonic, x[0].Operand1, x[j].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[0].Operand2) { continue; } break; } if (x[0].ignore) { continue; } } switch (x[0].Mnemonic) { case "pop": { Hashtable t = new Hashtable(); for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "push") { if (!t.Contains(x[j].Operand1)) { if (x[j].Operand1 == x[0].Operand1) { x[j].Ignore(); x[0].Ignore(); } else if (IsXX(x[j].Operand1) || IsXX(x[0].Operand1)) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("mov", x[0].Operand1, x[j].Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } else if (!t.Contains(x[0].Operand1)) { if (IsXX(x[j].Operand1) || IsXX(x[0].Operand1)) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("mov", x[0].Operand1, x[j].Operand1); xx.Notes = "[optimize] add"; i = list.IndexOf(x[j]); list.Insert(i + 1, xx); } } } else if (IsMovEtc(x[j].Mnemonic)) { t[x[j].Operand1] = true; continue; } break; } break; } case "cmp": if (IsXX(x[0].Operand1) && IsDigit(x[0].Operand2)) { for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[0].Operand1) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("cmp", x[j].Operand2, x[0].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[0].Operand1) { continue; } break; } } break; case "je": case "jne": case "jz": case "jnz": if (x[1].Mnemonic == "cmp" && IsXX(x[1].Operand1) && !IsDigit(x[1].Operand2)) { for (int j = 2; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[1].Operand1) { x[j].Ignore(); x[1].Ignore(); X86Code xx = new X86Code("cmp", x[1].Operand2, x[j].Operand2); xx.Notes = "[optimize] add"; i = list.IndexOf(x[1]); list.Insert(i + 1, xx); } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[1].Operand1) { continue; } break; } } break; case "mov": if (x.Length > 2 && IsAddEtc(x[1].Mnemonic) && x[2].Mnemonic == "mov" && x[0].Operand2 == x[1].Operand1 && x[1].Operand1 == x[2].Operand1) { if (x[1].Mnemonic == "inc" || x[1].Mnemonic == "dec") { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x[0].Operand1 == x[1].Operand2 && !IsAddr(x[2].Operand2)) { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1, x[2].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x[0].Operand1 == x[2].Operand2 && !IsAddr(x[1].Operand2)) { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1, x[1].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } break; case "add": if (x[0].Operand2 == "1") { x[0].Ignore(); X86Code xx = new X86Code("inc", x[0].Operand1); xx.Notes = "[Optimize] add"; list.Insert(i + 1, xx); } break; case "sub": if (x[0].Operand2 == "1") { x[0].Ignore(); X86Code xx = new X86Code("dec", x[0].Operand1); xx.Notes = "[Optimize] add"; list.Insert(i + 1, xx); } break; } } StringCollection jmp = new StringCollection(); for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } if (x.Mnemonic == "mov" && X86Code.IsXX(x.Operand1) && x.Operand2 == "0") { x.Ignore(); X86Code xx = new X86Code("xor", x.Operand1, x.Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x.Mnemonic == "mov" && x.Operand1 == x.Operand2) { x.Ignore(); } else if (x.Mnemonic.StartsWith("j")) { jmp.Add(x.Operand1); } } for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null) { continue; } if (x.IsBrTarget && !jmp.Contains(x.Label)) { x.IsBrTarget = false; } } }
public static void Optimize(ArrayList list) { for (int i = 1; i < list.Count; i++) { X86Code x0 = list[i] as X86Code; if (x0 == null || x0.ignore || x0.IsBrTarget) continue; ArrayList listx = new ArrayList(); listx.Add(x0); for (int j = 1;; j++) { X86Code xx = GetPrevious(list, i, j); if (xx == null) break; listx.Add(xx); } if (listx.Count < 2) continue; X86Code[] x = listx.ToArray(typeof(X86Code)) as X86Code[]; if (IsMovEtc(x[0].Mnemonic) && !IsXS(x[0].Operand1) && IsXX(x[0].Operand2) && x[0].Operand1 != x[0].Operand2) { for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[0].Operand2 && !IsXS(x[j].Operand2) && !(IsAddr(x[0].Operand1) && IsAddr(x[j].Operand2))) { if (x[0].Operand1 != x[j].Operand2 && (IsXX(x[0].Operand1) || IsXX(x[j].Operand2))) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[0].Mnemonic, x[0].Operand1, x[j].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[0].Operand2) { continue; } break; } if (x[0].ignore) continue; } switch (x[0].Mnemonic) { case "pop": { Hashtable t = new Hashtable(); for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "push") { if (!t.Contains(x[j].Operand1)) { if (x[j].Operand1 == x[0].Operand1) { x[j].Ignore(); x[0].Ignore(); } else if (IsXX(x[j].Operand1) || IsXX(x[0].Operand1)) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("mov", x[0].Operand1, x[j].Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } else if (!t.Contains(x[0].Operand1)) { if (IsXX(x[j].Operand1) || IsXX(x[0].Operand1)) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("mov", x[0].Operand1, x[j].Operand1); xx.Notes = "[optimize] add"; i = list.IndexOf(x[j]); list.Insert(i + 1, xx); } } } else if (IsMovEtc(x[j].Mnemonic)) { t[x[j].Operand1] = true; continue; } break; } break; } case "cmp": if (IsXX(x[0].Operand1) && IsDigit(x[0].Operand2)) { for (int j = 1; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[0].Operand1) { x[j].Ignore(); x[0].Ignore(); X86Code xx = new X86Code("cmp", x[j].Operand2, x[0].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[0].Operand1) { continue; } break; } } break; case "je": case "jne": case "jz": case "jnz": if (x[1].Mnemonic == "cmp" && IsXX(x[1].Operand1) && !IsDigit(x[1].Operand2)) { for (int j = 2; j < x.Length; j++) { if (x[j].Mnemonic == "mov" && x[j].Operand1 == x[1].Operand1) { x[j].Ignore(); x[1].Ignore(); X86Code xx = new X86Code("cmp", x[1].Operand2, x[j].Operand2); xx.Notes = "[optimize] add"; i = list.IndexOf(x[1]); list.Insert(i + 1, xx); } else if (IsMovEtc(x[j].Mnemonic) && x[j].Operand1 != x[1].Operand1) { continue; } break; } } break; case "mov": if (x.Length > 2 && IsAddEtc(x[1].Mnemonic) && x[2].Mnemonic == "mov" && x[0].Operand2 == x[1].Operand1 && x[1].Operand1 == x[2].Operand1) { if (x[1].Mnemonic == "inc" || x[1].Mnemonic == "dec") { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x[0].Operand1 == x[1].Operand2 && !IsAddr(x[2].Operand2)) { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1, x[2].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x[0].Operand1 == x[2].Operand2 && !IsAddr(x[1].Operand2)) { x[2].Ignore(); x[1].Ignore(); x[0].Ignore(); X86Code xx = new X86Code(x[1].Mnemonic, x[0].Operand1, x[1].Operand2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } } break; case "add": if (x[0].Operand2 == "1") { x[0].Ignore(); X86Code xx = new X86Code("inc", x[0].Operand1); xx.Notes = "[Optimize] add"; list.Insert(i + 1, xx); } break; case "sub": if (x[0].Operand2 == "1") { x[0].Ignore(); X86Code xx = new X86Code("dec", x[0].Operand1); xx.Notes = "[Optimize] add"; list.Insert(i + 1, xx); } break; } } StringCollection jmp = new StringCollection(); for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; if (x.Mnemonic == "mov" && X86Code.IsXX(x.Operand1) && x.Operand2 == "0") { x.Ignore(); X86Code xx = new X86Code("xor", x.Operand1, x.Operand1); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } else if (x.Mnemonic == "mov" && x.Operand1 == x.Operand2) { x.Ignore(); } else if (x.Mnemonic.StartsWith("j")) { jmp.Add(x.Operand1); } } for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null) continue; if (x.IsBrTarget && !jmp.Contains(x.Label)) x.IsBrTarget = false; } }
public void Optimize(ArrayList list, MethodData md) { X86Code.Optimize(list); bool bx = true; Hashtable locals = new Hashtable(); int max = 0; string target = null; for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; if (x.Mnemonic == "int" || x.Operand1 == "bx") bx = false; int p1a = x.Operand1.IndexOf("[ss:bp-"), p1b = x.Operand1.LastIndexOf(']'); if (0 <= p1a && p1a < p1b) { string var = x.Operand1.Substring(p1a + 1, p1b - p1a - 1); int v = !locals.Contains(var) ? 1 : ((int)locals[var]) + 1; locals[var] = v; if (max < v) { max = v; target = var; } } int p2a = x.Operand2.IndexOf("[ss:bp-"), p2b = x.Operand2.LastIndexOf(']'); if (0 <= p2a && p2a < p2b) { string var = x.Operand2.Substring(p2a + 1, p2b - p2a - 1); int v = !locals.Contains(var) ? 1 : ((int)locals[var]) + 1; locals[var] = v; if (max < v) { max = v; target = var; } } } if (bx && target != null) { for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; string op1 = x.Operand1, op2 = x.Operand2; int p1 = op1.IndexOf(target), p2 = op2.IndexOf(target); if (p1 >= 0) op1 = "bx"; if (p2 >= 0) op2 = "bx"; if (p1 < 0 && p2 < 0) continue; x.Ignore(); X86Code xx = new X86Code(x.Mnemonic, op1, op2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } if (md.LocalVars != null && md.LocalVars.Count == 1 && target.StartsWith("ss:bp-")) { for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; if (x.Mnemonic == "sub" && x.Operand1 == "sp") { x.Ignore(); break; } } for (int i = list.Count - 1; i >= 0; i--) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; if (x.Mnemonic == "mov" && x.Operand1 == "sp") { x.Ignore(); break; } } } } X86Code.Optimize(list); if (md.LocalVars != null || md.ParamCount > 0 || !bx) { X86Code xb1 = new X86Code("push", "bx"), xb2 = new X86Code("pop", "bx"); xb1.Notes = xb2.Notes = "[optimize] add"; list.Insert(0, xb1); for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) continue; if (x.Mnemonic == "ret") { list.Insert(i, xb2); i++; } } } }
public X86Codes ConvertIL(MethodData md, ILCode il) { string mne = il.OpCode.Name; if (mne == null) return null; X86Codes ret = new X86Codes(); ret.Address = il.Address; ret.IsBrTarget = il.IsBrTarget; if (il.Operand is byte) { ret.Comment = string.Format("{0} {1:X2}", mne, il.Operand); } else if (il.Operand is short) { ret.Comment = string.Format("{0} {1:X4}", mne, il.Operand); } else if (il.Operand is int) { ret.Comment = string.Format("{0} {1:X8}", mne, il.Operand); } else { ret.Comment = mne; } int mne_last = mne.Length < 1 ? 0 : (int)(mne[mne.Length - 1] - '0'); int nOp = Util.GetOperandValue(il); switch (mne) { case "ldc.i4": case "ldc.i4.s": case "ldc.i4.0": case "ldc.i4.1": case "ldc.i4.2": case "ldc.i4.3": case "ldc.i4.4": case "ldc.i4.5": case "ldc.i4.6": case "ldc.i4.7": case "ldc.i4.8": ret.Codes.Add(new X86Code("mov", "ax", nOp.ToString())); ret.Codes.Add(new X86Code("push", "ax")); break; case "ldloc": case "ldloc.s": case "ldloc.0": case "ldloc.1": case "ldloc.2": case "ldloc.3": ret.Codes.Add(new X86Code("push", string.Format("word [ss:bp-{0}]", (nOp + 1) * 2))); break; case "ldloca": case "ldloca.s": ret.Codes.Add(new X86Code("mov", "ax", "bp")); ret.Codes.Add(new X86Code("sub", string.Format("ax, {0}", (nOp + 1) * 2))); ret.Codes.Add(new X86Code("push", "ax")); break; case "stloc": case "stloc.s": case "stloc.0": case "stloc.1": case "stloc.2": case "stloc.3": ret.Codes.Add(new X86Code("pop", string.Format("word [ss:bp-{0}]", (nOp + 1) * 2))); break; case "ldarg": case "ldarg.s": case "ldarg.0": case "ldarg.1": case "ldarg.2": case "ldarg.3": ret.Codes.Add(new X86Code("push", string.Format("word [ss:bp+{0}]", Util.GetArgPos(md, nOp, this.optimize)))); break; case "starg": case "starg.s": ret.Codes.Add(new X86Code("pop", string.Format("word [ss:bp+{0}]", Util.GetArgPos(md, nOp, this.optimize)))); break; case "ldstr": { int us = ((int)il.Operand) & 0xffffff; if (!this.listUS.Contains(us)) this.listUS.Add(us); ret.Codes.Add(new X86Code("mov", "ax", string.Format("US_{0:X8}", us))); ret.Codes.Add(new X86Code("push", "ax")); break; } case "ldsfld": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); ret.Codes.Add(new X86Code("push", string.Format("word [cs:{0}]", MangleField(tb as FieldTable)))); break; } case "stsfld": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); ret.Codes.Add(new X86Code("pop", string.Format("word [cs:{0}]", MangleField(tb as FieldTable)))); break; } case "pop": ret.Codes.Add(new X86Code("pop", "ax")); break; case "br": case "br.s": ret.Codes.Add(new X86Code("jmp", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "beq": case "beq.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("je", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "bne.un": case "bne.un.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jne", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "bgt": case "bgt.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "blt": case "blt.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "dx", "ax")); ret.Codes.Add(new X86Code("jc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "ble": case "ble.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jnc near", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "bge": case "bge.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "dx", "ax")); ret.Codes.Add(new X86Code("jnc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "brfalse": case "brfalse.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("or", "ax", "ax")); ret.Codes.Add(new X86Code("jz", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "brtrue": case "brtrue.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("or", "ax", "ax")); ret.Codes.Add(new X86Code("jnz", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) ret.Ignore(); break; case "call": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); MethodData tb_md = tb.Tag as MethodData; ret.Codes.Add(new X86Code("call", string.Format("{0}", Util.MangleFunction(tb_md)))); if (tb_md.RetType.Element != ELEMENT_TYPE.VOID) ret.Codes.Add(new X86Code("push", "ax")); break; } //case "callvirt": //{ // TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); // MethodData tb_md = tb.Tag as MethodData; // string func = Util.MangleFunction(tb_md); // if (func.StartsWith("instance__")) func = func.Substring(10, func.Length - 10); // sw.WriteLine("\tcall _virtual__{0}", func); // if (tb_md.RetType.Element != ELEMENT_TYPE.VOID) sw.WriteLine("\tpush ax"); // break; //} case "ret": if (this.optimize == 0 || il == this.lastRet) { if (md.RetType.Element != ELEMENT_TYPE.VOID) { ret.Codes.Add(new X86Code("pop", "ax")); } if (md.LocalVars != null || md.ParamCount > 0) { if (md.LocalVars != null) ret.Codes.Add(new X86Code("mov", "sp", "bp")); ret.Codes.Add(new X86Code("pop", "bp")); } int st = Util.GetStackSize(md); if (st == 0) { ret.Codes.Add(new X86Code("ret")); } else { ret.Codes.Add(new X86Code("ret", st.ToString())); } } else { X86Code x = new X86Code("jmp", string.Format("PE_{0:X8}", this.lastRet.Address)); x.Notes = "[optimize] modify"; ret.Codes.Add(x); this.lastRet.IsBrTarget = true; } break; case "ceq": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("je", string.Format("NM_{0:X8}", this.number))); ret.Codes.Add(new X86Code("xor", "ax", "ax")); ret.Codes.Add(new X86Code("jmp", string.Format("NM_{0:X8}", this.number + 1))); ret.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number), true, "ceq internal", "mov", "ax", "1")); ret.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number + 1), true, "ceq internal", "push", "ax")); this.number += 2; break; case "add": case "and": case "or": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code(mne, "ax", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "sub": ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("sub", "ax", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "mul": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("mul", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "div": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("xor", "dx", "dx")); ret.Codes.Add(new X86Code("div", "cx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "rem": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("xor", "dx", "dx")); ret.Codes.Add(new X86Code("div", "cx")); ret.Codes.Add(new X86Code("push", "dx")); break; case "neg": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("neg", "ax")); ret.Codes.Add(new X86Code("push", "ax")); break; case "shr": case "shl": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code(mne, "ax", "cl")); ret.Codes.Add(new X86Code("push", "ax")); break; case "conv.u1": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("mov", "ah", "0")); ret.Codes.Add(new X86Code("push", "ax")); break; case "conv.i2": case "conv.u2": case "conv.i4": case "conv.u4": // ignore in 16bit return ret; //case "box": //{ // TypeRefTable t = this.pedata.idxm.GetTable((int)il.Operand) as TypeRefTable; // sw.WriteLine("\tcall _box__{0}@4", GetTypeName(this.pedata.idxm.GetName(t))); // sw.WriteLine("\tpush ax"); // break; //} } if (ret.Codes.Count < 1) return null; return ret; }
public object[] ConvertNative(MethodData md) { Stack st1 = new Stack(); foreach (ILCode il in md.ILCodes) { st1.Push(il); } this.lastRet = null; Stack st2 = new Stack(); while (st1.Count > 0) { ILCode il = st1.Pop() as ILCode; if (il.OpCode.Name == "ret" && this.lastRet == null) { this.lastRet = il; } else if (il.OpCode.Name == "pop" && st1.Count > 0) { ILCode il2 = st1.Peek() as ILCode; if (il2.OpCode.Name == "newobj") { TableBase tb = this.pedata.idxm.GetTable((int)il2.Operand); MethodData tb_md = tb.Tag as MethodData; if (tb_md.Name == "[I8086]I8086.Inline::.ctor" && st1.Count > 1) { st1.Pop(); ILCode il3 = st1.Peek() as ILCode; if (il3 != null && il3.OpCode.Name == "ldstr") { st1.Pop(); X86Codes nc = new X86Codes(); nc.Address = il3.Address; nc.IsBrTarget = il3.IsBrTarget; nc.Comment = "[native] inline"; nc.Codes.Add(X86Code.Parse(this.hashUS[((int)il3.Operand) & 0xffffff] as string)); st2.Push(nc); continue; } st1.Push(il2); } } } if (il.OpCode.Name == "call") { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); MethodData tb_md = tb.Tag as MethodData; string name = tb_md.Name; if (name.StartsWith("[I8086]I8086.Registers::set_")) { string reg = name.Substring(name.Length - 2, 2).ToLower(); if (st1.Count > 0 && !name.EndsWith("S")) { ILCode il2 = st1.Peek() as ILCode; string mne = il2.OpCode.Name; int nOp = Util.GetOperandValue(il2); if (mne.StartsWith("ldc.i4")) { st1.Pop(); X86Codes nc = new X86Codes(); nc.Address = il2.Address; nc.IsBrTarget = il2.IsBrTarget; nc.Comment = "[native] set register"; nc.Codes.Add(new X86Code("mov", reg, nOp.ToString())); st2.Push(nc); continue; } else if (mne.StartsWith("ldloc")) { st1.Pop(); X86Codes nc = new X86Codes(); nc.Address = il2.Address; nc.IsBrTarget = il2.IsBrTarget; nc.Comment = "[native] set register"; nc.Codes.Add(new X86Code("mov", reg, string.Format("[ss:bp-{0}]", (nOp + 1) * 2))); st2.Push(nc); continue; } else if (mne.StartsWith("ldarg")) { st1.Pop(); X86Codes nc = new X86Codes(); nc.Address = il2.Address; nc.IsBrTarget = il2.IsBrTarget; nc.Comment = "[native] set register"; nc.Codes.Add(new X86Code("mov", reg, string.Format("[ss:bp+{0}]", Util.GetArgPos(md, nOp, this.optimize)))); st2.Push(nc); continue; } } if (name.EndsWith("X") || name.EndsWith("I") || name.EndsWith("S")) { X86Codes nc = new X86Codes(); nc.Address = il.Address; nc.IsBrTarget = il.IsBrTarget; nc.Comment = "[native] set register"; nc.Codes.Add(new X86Code("pop", reg)); st2.Push(nc); continue; } } else if (name.StartsWith("[I8086]I8086.Registers::get_")) { X86Codes nc = new X86Codes(); nc.Address = il.Address; nc.IsBrTarget = il.IsBrTarget; nc.Comment = "[native] get register"; nc.Codes.Add(new X86Code("push", name.Substring(name.Length - 2, 2).ToLower())); st2.Push(nc); continue; } else if (name == "[I8086]I8086.IO::In" && st1.Count > 0) { ILCode il2 = st1.Peek() as ILCode; string mne = il2.OpCode.Name; int nOp = Util.GetOperandValue(il2); X86Codes nc = new X86Codes(); nc.Comment = "[native] in"; if (mne.StartsWith("ldc.i4")) { st1.Pop(); nc.Address = il2.Address; nc.IsBrTarget = il2.IsBrTarget; nc.Codes.Add(new X86Code("in", "al", nOp.ToString())); } else { nc.Address = il.Address; nc.IsBrTarget = il.IsBrTarget; nc.Codes.Add(new X86Code("pop", "dx")); nc.Codes.Add(new X86Code("in", "al", "dx")); } nc.Codes.Add(new X86Code("mov", "ah", "0")); nc.Codes.Add(new X86Code("push", "ax")); st2.Push(nc); continue; } else if (name == "[I8086]I8086.IO::Out") { X86Codes nc = new X86Codes(); nc.Address = il.Address; nc.IsBrTarget = il.IsBrTarget; nc.Comment = "[native] out"; nc.Codes.Add(new X86Code("pop", "ax")); nc.Codes.Add(new X86Code("pop", "dx")); nc.Codes.Add(new X86Code("out", "dx", "al")); st2.Push(nc); continue; } else if (name == "[I8086]I8086.StringPtr::Get") { continue; } else if (name.StartsWith("[I8086]I8086.Flags::get_")) { string mne = "jz"; int p = name.IndexOf('_') + 1; switch (name.Substring(p, name.Length - p)) { case "NZ": case "NE": mne = "jnz"; break; case "C": mne = "jc"; break; case "NC": mne = "jnc"; break; } X86Codes nc = new X86Codes(); nc.Address = il.Address; nc.IsBrTarget = il.IsBrTarget; nc.Comment = "[native] get flag"; nc.Codes.Add(new X86Code(mne, string.Format("NM_{0:X8}", this.number))); nc.Codes.Add(new X86Code("xor", "ax", "ax")); nc.Codes.Add(new X86Code("jmp", string.Format("NM_{0:X8}", this.number + 1))); nc.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number), true, "[native] get flag internal", "mov", "ax", "1")); nc.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number + 1), true, "[native] get flag internal", "push", "ax")); st2.Push(nc); this.number += 2; continue; } } st2.Push(il); } return(st2.ToArray()); }
public X86Codes ConvertIL(MethodData md, ILCode il) { string mne = il.OpCode.Name; if (mne == null) { return(null); } X86Codes ret = new X86Codes(); ret.Address = il.Address; ret.IsBrTarget = il.IsBrTarget; if (il.Operand is byte) { ret.Comment = string.Format("{0} {1:X2}", mne, il.Operand); } else if (il.Operand is short) { ret.Comment = string.Format("{0} {1:X4}", mne, il.Operand); } else if (il.Operand is int) { ret.Comment = string.Format("{0} {1:X8}", mne, il.Operand); } else { ret.Comment = mne; } int mne_last = mne.Length < 1 ? 0 : (int)(mne[mne.Length - 1] - '0'); int nOp = Util.GetOperandValue(il); switch (mne) { case "ldc.i4": case "ldc.i4.s": case "ldc.i4.0": case "ldc.i4.1": case "ldc.i4.2": case "ldc.i4.3": case "ldc.i4.4": case "ldc.i4.5": case "ldc.i4.6": case "ldc.i4.7": case "ldc.i4.8": ret.Codes.Add(new X86Code("mov", "ax", nOp.ToString())); ret.Codes.Add(new X86Code("push", "ax")); break; case "ldloc": case "ldloc.s": case "ldloc.0": case "ldloc.1": case "ldloc.2": case "ldloc.3": ret.Codes.Add(new X86Code("push", string.Format("word [ss:bp-{0}]", (nOp + 1) * 2))); break; case "ldloca": case "ldloca.s": ret.Codes.Add(new X86Code("mov", "ax", "bp")); ret.Codes.Add(new X86Code("sub", string.Format("ax, {0}", (nOp + 1) * 2))); ret.Codes.Add(new X86Code("push", "ax")); break; case "stloc": case "stloc.s": case "stloc.0": case "stloc.1": case "stloc.2": case "stloc.3": ret.Codes.Add(new X86Code("pop", string.Format("word [ss:bp-{0}]", (nOp + 1) * 2))); break; case "ldarg": case "ldarg.s": case "ldarg.0": case "ldarg.1": case "ldarg.2": case "ldarg.3": ret.Codes.Add(new X86Code("push", string.Format("word [ss:bp+{0}]", Util.GetArgPos(md, nOp, this.optimize)))); break; case "starg": case "starg.s": ret.Codes.Add(new X86Code("pop", string.Format("word [ss:bp+{0}]", Util.GetArgPos(md, nOp, this.optimize)))); break; case "ldstr": { int us = ((int)il.Operand) & 0xffffff; if (!this.listUS.Contains(us)) { this.listUS.Add(us); } ret.Codes.Add(new X86Code("mov", "ax", string.Format("US_{0:X8}", us))); ret.Codes.Add(new X86Code("push", "ax")); break; } case "ldsfld": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); ret.Codes.Add(new X86Code("push", string.Format("word [cs:{0}]", MangleField(tb as FieldTable)))); break; } case "stsfld": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); ret.Codes.Add(new X86Code("pop", string.Format("word [cs:{0}]", MangleField(tb as FieldTable)))); break; } case "pop": ret.Codes.Add(new X86Code("pop", "ax")); break; case "br": case "br.s": ret.Codes.Add(new X86Code("jmp", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "beq": case "beq.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("je", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "bne.un": case "bne.un.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jne", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "bgt": case "bgt.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "blt": case "blt.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "dx", "ax")); ret.Codes.Add(new X86Code("jc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "ble": case "ble.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("jnc near", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "bge": case "bge.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "dx", "ax")); ret.Codes.Add(new X86Code("jnc", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "brfalse": case "brfalse.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("or", "ax", "ax")); ret.Codes.Add(new X86Code("jz", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "brtrue": case "brtrue.s": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("or", "ax", "ax")); ret.Codes.Add(new X86Code("jnz", string.Format("PE_{0:X8}", Girl.PEAnalyzer.Util.GetBrTarget(il)))); if (this.optimize > 0 && nOp == 0) { ret.Ignore(); } break; case "call": { TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); MethodData tb_md = tb.Tag as MethodData; ret.Codes.Add(new X86Code("call", string.Format("{0}", Util.MangleFunction(tb_md)))); if (tb_md.RetType.Element != ELEMENT_TYPE.VOID) { ret.Codes.Add(new X86Code("push", "ax")); } break; } //case "callvirt": //{ // TableBase tb = this.pedata.idxm.GetTable((int)il.Operand); // MethodData tb_md = tb.Tag as MethodData; // string func = Util.MangleFunction(tb_md); // if (func.StartsWith("instance__")) func = func.Substring(10, func.Length - 10); // sw.WriteLine("\tcall _virtual__{0}", func); // if (tb_md.RetType.Element != ELEMENT_TYPE.VOID) sw.WriteLine("\tpush ax"); // break; //} case "ret": if (this.optimize == 0 || il == this.lastRet) { if (md.RetType.Element != ELEMENT_TYPE.VOID) { ret.Codes.Add(new X86Code("pop", "ax")); } if (md.LocalVars != null || md.ParamCount > 0) { if (md.LocalVars != null) { ret.Codes.Add(new X86Code("mov", "sp", "bp")); } ret.Codes.Add(new X86Code("pop", "bp")); } int st = Util.GetStackSize(md); if (st == 0) { ret.Codes.Add(new X86Code("ret")); } else { ret.Codes.Add(new X86Code("ret", st.ToString())); } } else { X86Code x = new X86Code("jmp", string.Format("PE_{0:X8}", this.lastRet.Address)); x.Notes = "[optimize] modify"; ret.Codes.Add(x); this.lastRet.IsBrTarget = true; } break; case "ceq": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("cmp", "ax", "dx")); ret.Codes.Add(new X86Code("je", string.Format("NM_{0:X8}", this.number))); ret.Codes.Add(new X86Code("xor", "ax", "ax")); ret.Codes.Add(new X86Code("jmp", string.Format("NM_{0:X8}", this.number + 1))); ret.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number), true, "ceq internal", "mov", "ax", "1")); ret.Codes.Add(new X86Code(string.Format("NM_{0:X8}", this.number + 1), true, "ceq internal", "push", "ax")); this.number += 2; break; case "add": case "and": case "or": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code(mne, "ax", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "sub": ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("sub", "ax", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "mul": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("pop", "dx")); ret.Codes.Add(new X86Code("mul", "dx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "div": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("xor", "dx", "dx")); ret.Codes.Add(new X86Code("div", "cx")); ret.Codes.Add(new X86Code("push", "ax")); break; case "rem": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("xor", "dx", "dx")); ret.Codes.Add(new X86Code("div", "cx")); ret.Codes.Add(new X86Code("push", "dx")); break; case "neg": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("neg", "ax")); ret.Codes.Add(new X86Code("push", "ax")); break; case "shr": case "shl": ret.Codes.Add(new X86Code("pop", "cx")); ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code(mne, "ax", "cl")); ret.Codes.Add(new X86Code("push", "ax")); break; case "conv.u1": ret.Codes.Add(new X86Code("pop", "ax")); ret.Codes.Add(new X86Code("mov", "ah", "0")); ret.Codes.Add(new X86Code("push", "ax")); break; case "conv.i2": case "conv.u2": case "conv.i4": case "conv.u4": // ignore in 16bit return(ret); //case "box": //{ // TypeRefTable t = this.pedata.idxm.GetTable((int)il.Operand) as TypeRefTable; // sw.WriteLine("\tcall _box__{0}@4", GetTypeName(this.pedata.idxm.GetName(t))); // sw.WriteLine("\tpush ax"); // break; //} } if (ret.Codes.Count < 1) { return(null); } return(ret); }
public void Optimize(ArrayList list, MethodData md) { X86Code.Optimize(list); bool bx = true; Hashtable locals = new Hashtable(); int max = 0; string target = null; for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } if (x.Mnemonic == "int" || x.Operand1 == "bx") { bx = false; } int p1a = x.Operand1.IndexOf("[ss:bp-"), p1b = x.Operand1.LastIndexOf(']'); if (0 <= p1a && p1a < p1b) { string var = x.Operand1.Substring(p1a + 1, p1b - p1a - 1); int v = !locals.Contains(var) ? 1 : ((int)locals[var]) + 1; locals[var] = v; if (max < v) { max = v; target = var; } } int p2a = x.Operand2.IndexOf("[ss:bp-"), p2b = x.Operand2.LastIndexOf(']'); if (0 <= p2a && p2a < p2b) { string var = x.Operand2.Substring(p2a + 1, p2b - p2a - 1); int v = !locals.Contains(var) ? 1 : ((int)locals[var]) + 1; locals[var] = v; if (max < v) { max = v; target = var; } } } if (bx && target != null) { for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } string op1 = x.Operand1, op2 = x.Operand2; int p1 = op1.IndexOf(target), p2 = op2.IndexOf(target); if (p1 >= 0) { op1 = "bx"; } if (p2 >= 0) { op2 = "bx"; } if (p1 < 0 && p2 < 0) { continue; } x.Ignore(); X86Code xx = new X86Code(x.Mnemonic, op1, op2); xx.Notes = "[optimize] add"; list.Insert(i + 1, xx); } if (md.LocalVars != null && md.LocalVars.Count == 1 && target.StartsWith("ss:bp-")) { for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } if (x.Mnemonic == "sub" && x.Operand1 == "sp") { x.Ignore(); break; } } for (int i = list.Count - 1; i >= 0; i--) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } if (x.Mnemonic == "mov" && x.Operand1 == "sp") { x.Ignore(); break; } } } } X86Code.Optimize(list); if (md.LocalVars != null || md.ParamCount > 0 || !bx) { X86Code xb1 = new X86Code("push", "bx"), xb2 = new X86Code("pop", "bx"); xb1.Notes = xb2.Notes = "[optimize] add"; list.Insert(0, xb1); for (int i = 0; i < list.Count; i++) { X86Code x = list[i] as X86Code; if (x == null || x.ignore) { continue; } if (x.Mnemonic == "ret") { list.Insert(i, xb2); i++; } } } }