[+] Every instruction supports converting to FASM code now.

This commit is contained in:
LostTheBlack_cp 2008-04-11 10:24:33 +00:00
parent 10c45343bf
commit c2cf1cefcb
24 changed files with 219 additions and 592 deletions

View file

@ -48,5 +48,10 @@ namespace Lost.JIT.AMD64
{
get { return 0x10; }
}
public override string OpCodeFASM
{
get { return "adc"; }
}
}
}

View file

@ -49,5 +49,10 @@ namespace Lost.JIT.AMD64
{
get { return 0x20; }
}
public override string OpCodeFASM
{
get { return "and"; }
}
}
}

View file

@ -18,5 +18,14 @@ namespace Lost.JIT.AMD64
{
destStream.WriteByte(0xCC);
}
public override string OpCodeFASM
{
get { return "int 3"; }
}
public override string ToFASM()
{
return OpCodeFASM;
}
}
}

View file

@ -68,5 +68,15 @@ namespace Lost.JIT.AMD64
throw new NotImplementedException();
}
public override string OpCodeFASM
{
get { return "call"; }
}
public override string ToFASM()
{
return string.Format(Dest is MemoryOperand? "call qword {0}": "call {0}", Dest);
}
}
}

View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Lost.JIT.AMD64
{
[Serializable]
public sealed class Compare : DestSourceInstruction
{
public Compare(InstructionOperand dest, InstructionOperand source)
: base(dest, source)
{
}
public Compare(InstructionOperand dest, byte source)
: base(dest, source)
{
}
public Compare(InstructionOperand dest, short source)
: base(dest, source)
{
}
public Compare(InstructionOperand dest, int source)
: base(dest, source)
{
}
public Compare(InstructionOperand dest, long source)
: base(dest, source)
{
}
public override byte AccumulatorOpCode
{
get
{
return 0x3C;
}
}
public override byte ImmediateExt
{
get { return 0x07; }
}
public override byte ImmediateOpCode
{
get { return 0x80; }
}
public override byte RegisterOpCode
{
get { return 0x38; }
}
public override string OpCodeFASM
{
get { return "cmp"; }
}
}
}

View file

@ -23,7 +23,7 @@ namespace Lost.JIT.AMD64
public override void Compile(Stream destStream)
{
if (TargetOffset.FitsInByte())
if (TargetOffset.FitsInSByte())
{
destStream.WriteByte(OpcodeBase);
destStream.WriteSByte(TargetOffset);
@ -37,5 +37,11 @@ namespace Lost.JIT.AMD64
}
protected abstract int OpcodeBase { get; }
public override string ToFASM()
{
return string.Format("{0} {1}", OpCodeFASM,
TargetOffset + (TargetOffset.FitsInSByte() ? 2 : 6));
}
}
}

View file

@ -277,6 +277,11 @@ namespace Lost.JIT.AMD64
get { throw new NotImplementedException(); }
}
public override string ToFASM()
{
return string.Format("{0} {1}, {2}", OpCodeFASM, Dest, Source);
}
/// <summary>
/// INSTR accum, imm
/// </summary>

View file

@ -6,7 +6,7 @@ using System.Text;
namespace Lost.JIT.AMD64
{
[Serializable]
public sealed class GeneralPurposeRegister: InstructionOperand
public sealed class GeneralPurposeRegister: InstructionOperand, IEquatable<GeneralPurposeRegister>
{
public GeneralPurposeRegister(Registers register, int size)
{
@ -17,6 +17,28 @@ namespace Lost.JIT.AMD64
public int Size { get; private set; }
public Registers Register { get; private set; }
public override string ToString()
{
if (Register.IsNew() && (Size == 8)) return Register.ToString();
if (!Register.IsNew())
{
switch(Size)
{
case 2:
return Register.ToString();
case 4:
return 'E' + Register.ToString();
case 8:
return 'R' + Register.ToString();
case 1:
return Register.ToString().Substring(0, 1)+ 'L';
default:
throw new NotImplementedException();
}
}
throw new NotImplementedException();
}
public static readonly GeneralPurposeRegister RAX = new GeneralPurposeRegister(Registers.AX, 8);
public static readonly GeneralPurposeRegister RBX = new GeneralPurposeRegister(Registers.BX, 8);
public static readonly GeneralPurposeRegister RCX = new GeneralPurposeRegister(Registers.CX, 8);
@ -60,5 +82,15 @@ namespace Lost.JIT.AMD64
//public static readonly GeneralPurposeRegister DI = new GeneralPurposeRegister(Registers.DI, 1);
//public static readonly GeneralPurposeRegister BP = new GeneralPurposeRegister(Registers.BP, 1);
//public static readonly GeneralPurposeRegister SP = new GeneralPurposeRegister(Registers.SP, 1);
#region IEquatable<GeneralPurposeRegister> Members
public bool Equals(GeneralPurposeRegister other)
{
if (other == null) return false;
return (other.Register == Register) && (other.Size == Size);
}
#endregion
}
}

View file

@ -32,5 +32,11 @@ namespace Lost.JIT.AMD64
public long Value { get; private set; }
public int Size { get; private set; }
public override string ToString()
{
string digs = (Size * 2).ToString();
return "0x" + Value.ToString("X" + digs);
}
}
}

View file

@ -40,5 +40,21 @@ namespace Lost.JIT.AMD64
throw new NotImplementedException();
}
public override string OpCodeFASM
{
get { return "jmp"; }
}
public override string ToFASM()
{
if (Dest is ImmediateOperand)
{
var dest = Dest as ImmediateOperand;
return string.Format("jmp {0}", dest.Value + (dest.Value.FitsInSByte()? 2: 5));
}
throw new NotImplementedException();
}
}
}

View file

@ -14,5 +14,10 @@ namespace Lost.JIT.AMD64
{
get { return 0x74; }
}
public override string OpCodeFASM
{
get { return "je"; }
}
}
}

View file

@ -44,5 +44,24 @@ namespace Lost.JIT.AMD64
}
return Base != null;
}
public override string ToString()
{
if (RipBased)
return string.Format("[RIP + 0x{0}]", Displacement.ToString("X8"));
var sb = new StringBuilder();
sb.AppendFormat("[{0}", Base);
if (Index != null)
if (Scale > 1)
sb.AppendFormat(" + {0}*{1}", Index, Scale);
else
sb.AppendFormat(" + {0}", Index);
if (Displacement != 0)
sb.AppendFormat(" + 0x{0}", Displacement.ToString("X16"));
sb.Append(']');
return sb.ToString();
}
}
}

View file

@ -52,5 +52,14 @@ namespace Lost.JIT.AMD64
}
throw new InvalidProgramException();
}
public override string OpCodeFASM
{
get { return "pop"; }
}
public override string ToFASM()
{
return string.Format(Dest is MemoryOperand? "pop qword {0}":"pop {0}", Dest);
}
}
}

View file

@ -13,8 +13,15 @@ namespace Lost.JIT.AMD64
public const byte AddressSizeOverride = 0x67;
public abstract int? Size { get; }
public abstract string ToFASM();
public abstract string OpCodeFASM { get; }
public abstract void Compile(Stream destStream);
public override string ToString()
{
return ToFASM();
}
public static Rex NeedsRex(MemoryOperand memory)
{
if (memory.RipBased) return Rex.None;

View file

@ -73,5 +73,14 @@ namespace Lost.JIT.AMD64
}
}
}
public override string OpCodeFASM
{
get { return "push"; }
}
public override string ToFASM()
{
return string.Format(Source is MemoryOperand ? "push qword {0}" : "push {0}", Source);
}
}
}

View file

@ -1,74 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Lost.JIT.AMD64OLD
{
[Flags]
enum Register: byte
{
Legacy = 0x07,
AX = 0x00,
BX = 0x03,
CX = 0x01,
DX = 0x02,
SP = 0x04,
BP = 0x05,
SI = 0x06,
DI = 0x07,
R8 = 0x08,
R9 = 0x09,
R10 = 0x0A,
R11 = 0x0B,
R12 = 0x0C,
R13 = 0x0D,
R14 = 0x0E,
R15 = 0x0F,
}
[Flags]
public enum Rex : byte
{
None = 0x40,
/// <summary>
/// Use 64-bit operand size
/// </summary>
/// <remarks>
/// Setting the REX.W bit to 1 specifies a 64-bit operand size. Like the
/// existing 66h operand-size prefix, the REX 64-bit operand-size override has no effect on byte
/// operations. For non-byte operations, the REX operand-size override takes precedence over the 66h
/// prefix. If a 66h prefix is used together with a REX prefix that has the REX.W bit set to 1, the 66h
/// prefix is ignored. However, if a 66h prefix is used together with a REX prefix that has the REX.W bit
/// cleared to 0, the 66h prefix is not ignored and the operand size becomes 16 bits.
///</remarks>
Wide = None | (1 << 3),
/// <summary>
/// Reg index from ModRM extension.
/// </summary>
/// <remarks>
/// The REX.R bit adds a 1-bit (high) extension to the ModRM reg field (page 17)
/// when that field encodes a GPR, XMM, control, or debug register. REX.R does not modify ModRM reg
/// when that field specifies other registers or opcodes. REX.R is ignored in such cases.
/// </remarks>
Reg = None | (1 << 2),
/// <summary>
/// SIB index register extension.
/// </summary>
Index = None | (1 << 1),
/// <summary>
/// SIB index register extension.
/// Use Index mnenonic instead.
/// </summary>
X = None | (1 << 1),
/// <summary>
/// Extension of the ModRM r/m field1, SIB base field, or opcode reg field,
/// </summary>
/// <remarks>
/// The REX.B bit adds a 1-bit (high) extension to either the ModRM r/m field to specify
/// a GPR or XMM register, or to the SIB base field to specify a GPR. (See Table 2-2 on page 40 for more
/// about the REX.B bit.)
/// </remarks>
B = None | (1 << 0),
}
}

View file

@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Lost.JIT.AMD64OLD
{
[Obsolete("")]
class ImmediateOperand: InstructionOperand
{
internal ImmediateOperand(int size, ulong value):base(value.ToString(string.Format("0X{0}", size*2)))
{
switch (size)
{
case 1:
byte b = checked((byte)value);
break;
case 2:
ushort s = checked((ushort)value);
break;
case 4:
uint i = checked((uint)value);
break;
case 8:
break;
default:
throw new NotSupportedException("incorrect operand size");
}
_size = size;
_value = (long)value;
}
int _size;
long _value;
/// <summary>
/// Size of immediate operand, in bytes
/// </summary>
public int Size
{
get { return _size; }
}
/// <summary>
/// Value of immediate operand
/// </summary>
public long Value
{
get { return _value; }
}
public override string ToString()
{
var val = _value.ToString(string.Format("X{0}", Size*2));
return string.Format("0{0}h", val);
}
}
}

View file

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Lost.JIT.AMD64OLD
{
class InstructionLabel
{
internal InstructionLabel(string name)
{
_name = name;
#warning TODO: check label for validity
}
static readonly Regex _regex = new Regex(
@"^(\s*(?<label>\w+)\u003A)*(?<rest>.*$)",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
public static InstructionLabel[] ExtractLabels(ref string instruction)
{
var match = _regex.Match(instruction);
var result = new InstructionLabel[match.Groups["label"].Captures.Count];
for (int i = 0; i < result.Length; i++)
result[i] = new InstructionLabel(match.Groups["label"].Captures[i].Value);
instruction = match.Groups["rest"].Value;
return result;
}
public string Name
{
get { return _name; }
} string _name;
public override string ToString()
{
return string.Format("{0}:", Name);
}
}
}

View file

@ -1,109 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
namespace Lost.JIT.AMD64OLD
{
class InstructionOperand
{
public InstructionOperand(string value)
{
_stringValue = value;
}
static readonly Regex _regex = new Regex(
@"^(\s*(?<operand>(\w|\[|\]|\+|\-)+)\s*\,)*\s*$",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
internal static InstructionOperand[] GetOperands(string code)
{
if (code.Trim() != "") code += ",";
var match = _regex.Match(code);
var result = new InstructionOperand[match.Groups["operand"].Captures.Count];
for (int i = 0; i < result.Length; i++)
result[i] = InstructionOperand.Parse(match.Groups["operand"].Captures[i].Value);
return result;
}
private static InstructionOperand Parse(string operand)
{
return new InstructionOperand(operand);
}
string _stringValue;
public override string ToString()
{
return _stringValue;
}
#region Parsing stuff
public bool IsGeneralPurposeRegister
{
get
{
if (_isGeneralPurposeRegister == null)
throw new NotImplementedException();
return _isGeneralPurposeRegister.Value;
}
} bool? _isGeneralPurposeRegister;
public int Size
{
get
{
if (_size == null)
throw new NotImplementedException();
return _size.Value;
}
} int? _size;
public ulong Value
{
get
{
if (_value == null) throw new NotImplementedException();
return _value.Value;
}
} ulong? _value;
public Register Register
{
get
{
if (_register == null)
throw new NotImplementedException();
return _register.Value;
}
} Register? _register;
public bool IsImmediate
{
get
{
if (_immediate == null)
throw new NotImplementedException();
return _immediate.Value;
}
} bool? _immediate;
public void WriteTo(Stream dest)
{
Debug.Assert(IsImmediate);
ulong value = Value;
for (int i = 0; i < Size; i++, value >>= 8)
dest.WriteByte((byte)(value & 0xFF));
}
#endregion
}
}

View file

@ -1,62 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace Lost.JIT.AMD64OLD
{
class InstructionPrefix
{
public InstructionPrefix(string name)
{
if (!_prefixes.Contains(name))
throw new ArgumentException("name");
_name = name;
}
public string Name
{
get { return _name; }
} string _name;
public override string ToString()
{
return Name;
}
#region Parsing
static readonly HashSet<string> _prefixes = new HashSet<string>() {
"lock",
};
static InstructionPrefix()
{
var sb = new StringBuilder();
foreach (var prefix in _prefixes) sb.AppendFormat("{0}|", prefix);
Debug.Assert(sb.Length > 0);
sb.Remove(sb.Length - 1, 1);
_regex = new Regex(
string.Format(@"^(\s*(?<prefix>({0})))*(?<rest>.*$)", sb),
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
}
static readonly Regex _regex;
public static InstructionPrefix[] ExtractPrefixes(ref string instruction)
{
var match = _regex.Match(instruction);
var result = new InstructionPrefix[match.Groups["prefix"].Captures.Count];
for (int i = 0; i < result.Length; i++)
result[i] = new InstructionPrefix(match.Groups["prefix"].Captures[i].Value);
instruction = match.Groups["rest"].Value;
return result;
}
#endregion
}
}

View file

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace Lost.JIT.AMD64OLD
{
static class ModRM
{
public static void EncodeRegisters(this Stream dest, Register destReg, Register sourceReg)
{
destReg &= Register.Legacy;
sourceReg &= Register.Legacy;
byte result = 0xC0; //11000000b
result |= (byte)(((byte)destReg) << 3 | (byte)sourceReg);
dest.WriteByte(result);
}
public static void EncodeIndirectMemory(this Stream dest, byte xcode, Register baseReg)
{
Debug.Assert((xcode & ~(byte)Register.Legacy) == 0);
byte modRM =(byte)((xcode << 3) | (byte)baseReg);
dest.WriteByte(modRM);
}
}
}

View file

@ -1,201 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
namespace Lost.JIT.AMD64OLD
{
class ProcessorInstruction
{
const byte Lock = 0xF0;
const byte OperandSizeOverride = 0x66;
const byte AddressSizeOverride = 0x67;
const byte Rep = 0xF3;
const byte RepE = 0xF3;
const byte RepNE = 0xF2;
internal ProcessorInstruction()
{
_labels = new HashSet<InstructionLabel>();
_prefixes = new HashSet<InstructionPrefix>();
}
internal ProcessorInstruction(string opCode, InstructionOperand[] operands, InstructionLabel[] labels, InstructionPrefix[] prefixes, string comments)
{
_opCode = opCode;
_operands = new List<InstructionOperand>(operands);
_labels = new HashSet<InstructionLabel>(labels);
_prefixes = new HashSet<InstructionPrefix>(prefixes);
_comments = comments;
}
ICollection<InstructionLabel> Labels
{
get { return _labels; }
} HashSet<InstructionLabel> _labels;
ICollection<InstructionPrefix> Prefixes
{
get { return _prefixes; }
} HashSet<InstructionPrefix> _prefixes;
IList<InstructionOperand> Operands
{
get { return _operands; }
} List<InstructionOperand> _operands;
string OpCode
{
get { return _opCode; }
} string _opCode;
string Comments
{
get { return _comments; }
} string _comments;
#region Encoding
InstructionOperand Dest
{
get { return _operands[0]; }
}
InstructionOperand Source
{
get { return _operands[1]; }
}
#region Instructions
void AddWithCarry(Stream dest)
{
if (Dest.IsGeneralPurposeRegister)
if (Dest.Register == Register.AX && Source.IsImmediate)
{
switch (Dest.Size)
{
case 1:
if (Source.Size != null)
Debug.Assert(Source.Size == 1);
dest.WriteByte(0x14);
break;
case 2:
if (Source.Size != null)
Debug.Assert(Source.Size == 2);
dest.WriteByte(OperandSizeOverride);
dest.WriteByte(0x15);
break;
case 4:
if (Source.Size != null)
Debug.Assert(Source.Size == 4);
dest.WriteByte(0x15);
break;
case 8:
if (Source.Size != null)
Debug.Assert(Source.Size == 4);
dest.WriteByte((byte)Rex.Wide);
dest.WriteByte(0x15);
break;
default:
throw new NotSupportedException();
}
Source.WriteTo(dest);
return;
} //adc al/ax/etc, imm
if (Source.IsImmediate)
{
switch (Dest.Size)
{
case 1:
if (Source.Size != null)
Debug.Assert(Source.Size == 4);
dest.WriteByte(AddressSizeOverride);
dest.WriteByte(0x80);
dest.EncodeIndirectMemory(2, Dest.Register);
break;
}
Source.WriteTo(dest);
return;
}
Debug.Assert(false);
}
#endregion
public void Encode(Stream dest)
{
switch (_opCode)
{
case "adc":
AddWithCarry(dest);
break;
default:
throw new NotSupportedException(_opCode);
}
}
static void EncodeRegisterRegister(Rex rex, Register dest, Register source, byte opcode, Stream stream)
{
if (rex != Rex.None) stream.WriteByte((byte)rex);
stream.WriteByte(opcode);
stream.EncodeRegisters(dest, source);
}
static void EncodeRegister(Rex rex, Register dest, byte opcode, Stream stream)
{
if (rex != Rex.None) stream.WriteByte((byte)rex);
dest &= Register.Legacy;
Debug.Assert((opcode | (byte)Register.Legacy) == 0);
opcode |= (byte)dest;
stream.WriteByte(opcode);
}
#endregion
#region Parsing
public static ProcessorInstruction Parse(string code)
{
var labels = InstructionLabel.ExtractLabels(ref code);
var prefixes = InstructionPrefix.ExtractPrefixes(ref code);
var instr = ExtractInstruction(ref code);
var comments = ExtractComments(ref code);
var operands = InstructionOperand.GetOperands(code);
var result = new ProcessorInstruction(instr.ToUpper(), operands, labels, prefixes, comments);
return result;
}
static readonly Regex _regexComments = new Regex(
@"^(?<rest>.*)\/\/\s*(?<comments>.*)\s*$",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static string ExtractComments(ref string code)
{
var match = _regexComments.Match(code);
if (match == null) return null;
if (!match.Success) return null;
var value = match.Groups["comments"].Value;
code = match.Groups["rest"].Value;
return value;
}
static readonly Regex _regexInstruction = new Regex(
@"^\s*(?<instr>\w+)(?<rest>.*$)",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static string ExtractInstruction(ref string code)
{
var match = _regexInstruction.Match(code);
var value = match.Groups["instr"].Value;
code = match.Groups["rest"].Value;
return value;
}
#endregion
}
}

View file

@ -52,17 +52,11 @@
<ItemGroup>
<Compile Include="BinaryStreamExtensions.cs" />
<Compile Include="BitUtils.cs" />
<Compile Include="JIT\AMD64OLD\Enumerations.cs" />
<Compile Include="JIT\AMD64OLD\ImmediateOperand.cs" />
<Compile Include="JIT\AMD64OLD\InstructionLabel.cs" />
<Compile Include="JIT\AMD64OLD\InstructionOperand.cs" />
<Compile Include="JIT\AMD64OLD\InstructionPrefix.cs" />
<Compile Include="JIT\AMD64OLD\ModRM.cs" />
<Compile Include="JIT\AMD64OLD\ProcessorInstruction.cs" />
<Compile Include="JIT\AMD64\AddWithCarry.cs" />
<Compile Include="JIT\AMD64\And.cs" />
<Compile Include="JIT\AMD64\BreakPoint.cs" />
<Compile Include="JIT\AMD64\Call.cs" />
<Compile Include="JIT\AMD64\Compare.cs" />
<Compile Include="JIT\AMD64\ConditionalJumpInstruction.cs" />
<Compile Include="JIT\AMD64\DestSourceInstruction.cs" />
<Compile Include="JIT\AMD64\ImmediateOperand.cs" />

View file

@ -31,7 +31,8 @@ namespace Lost
static string RunFasm(string filename, string dest)
{
const string fasm = @"C:\Programs\Devel\asm\fasmw16726\fasm.exe";
//C:\Programs\Devel\asm\fasmw16726\
const string fasm = @"fasm.exe";
var par = new ProcessStartInfo(fasm, string.Format("\"{0}\" \"{1}\"", filename, dest));
@ -83,7 +84,7 @@ namespace Lost
Test("adc [rsp + 0xFFF], eax",
new AddWithCarry(new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.SP,
Base = GeneralPurposeRegister.RSP,
}, GeneralPurposeRegister.EAX));
Test("adc al, [rax*2 + r11]",
@ -95,7 +96,7 @@ namespace Lost
}));
#endregion
#region ADC
#region AND
Test("and al, 1", new And(GeneralPurposeRegister.AL, (byte)1));
Test("and rcx, 1", new And(GeneralPurposeRegister.RCX, (byte)1));
Test("and rcx, 0xFFF", new And(GeneralPurposeRegister.RCX, 0xFFF));
@ -117,7 +118,7 @@ namespace Lost
Test("and [rsp + 0xFFF], eax",
new And(new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.SP,
Base = GeneralPurposeRegister.RSP,
}, GeneralPurposeRegister.EAX));
Test("and al, [rax*2 + r11]",
@ -153,7 +154,7 @@ namespace Lost
new Pop(
new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.SP,
Base = GeneralPurposeRegister.RSP,
}));
Test("pop qword [r12*8 + r11]",
new Pop(
@ -198,8 +199,16 @@ namespace Lost
#endregion
}
static void Test(string fasm_code, ProcessorInstruction my_code)
static void Test(ProcessorInstruction my_code)
{
Test(null, my_code);
}
static void Test(
string xxx,
ProcessorInstruction my_code)
{
string fasm_code = my_code.ToFASM();
using (var writer = new StreamWriter(tempFile))
{
writer.WriteLine("use64");