static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("ubpldir.exe filename"); Environment.Exit(1); } using var stream = File.OpenRead(args[0]); Span <byte> binary = stackalloc byte[16]; Span <uint> values = stackalloc uint[4]; int index = 0; while (stream.Read(binary) > 0) { ToUint(binary, values); Mnemonic mnemonic = (Mnemonic)values[0]; ModRm modRm = new ModRm(values[1]); string head = ToOperandString(modRm.HeadMode, modRm.HeadReg1, modRm.HeadReg2, values[2]); string tail = ToOperandString(modRm.TailMode, modRm.TailReg1, modRm.TailReg2, values[3]); Console.Write("{0:X08}: ", index); Console.Write("{0:X08} {1:X08} {2:X08} {3:X08} | ", values[0], values[1], values[2], values[3]); Console.WriteLine("{0,-6} {1} {2}", mnemonic, head, tail); index += 16; binary.Fill(0); } }
public Code() { Mnemonic = Mnemonic.KRZ; Modrm = new ModRm(0U); Head = Operand.F0; Tail = Operand.F0; }
private ModRm ToModRm(Operand opd) { ModRm modrm = new ModRm(); if (opd.IsLabel) { modrm.Reg = (byte)Register.F0; modrm.Mode = 6; modrm.Disp32 = 0; } else if (opd.IsImm) { modrm.Reg = 0; modrm.Mode = GetDispType(opd.Disp.Value); modrm.Disp32 = opd.Disp.Value; } else if (opd.SecondReg.HasValue) { if (opd.IsAddress) { modrm.Reg = (byte)opd.Reg.Value; modrm.Mode = (byte)(0b11000 | (byte)opd.SecondReg.Value); modrm.Disp32 = 0U; } else { throw new ArgumentException(); } } else if (opd.Disp.HasValue) { modrm.Reg = (byte)opd.Reg.Value; if (opd.IsAddress) { modrm.Mode = (byte)(0b10000 | GetDispType(opd.Disp.Value)); modrm.Disp32 = opd.Disp.Value; } else { throw new ArgumentException(); } } else { modrm.Reg = (byte)opd.Reg.Value; modrm.Mode = (byte)(opd.IsAddress ? 0b10000 : 0); modrm.Disp32 = 0U; } return(modrm); }
private int GetDispLength(ModRm modrm) { if ((modrm.Mode & 0x18U) == 0x18U || modrm.Mode == 0U) { return(0); } switch (modrm.Mode & 7U) { case 4: return(1); case 5: return(2); case 6: return(4); default: return(0); } }
private void WriteModRm(BinaryWriter writer, ModRm modrm) { uint disp = modrm.DispImm; writer.Write(modrm.Code); if ((modrm.Mode & 0x18) == 0x18) { return; } int count; switch (modrm.Mode & 0x7) { case 0x4: count = 3; break; case 0x5: count = 2; break; case 0x6: count = 0; break; default: count = 4; break; } for (int i = count; i < 4; i++) { writer.Write((byte)(disp >> ((3 - i) * 8))); } }
/// <summary> /// バイナリを出力します /// </summary> /// <returns>変換結果</returns> public IReadOnlyList <byte> ToBinaryCode() { int lifemBinarySize = _lifemValues.Count << 2; int binarySize = (_codes.Count << 4) + lifemBinarySize - (lifemBinarySize & 0xF) + 16; List <byte> binaryCode = new List <byte>(binarySize); List <byte> lifemBinary = new List <byte>(lifemBinarySize); uint count = (uint)_codes.Count * 16U; Span <byte> buffer = stackalloc byte[4]; // lifemのラベル処理,バイナリ化 foreach (var lifemValue in _lifemValues) { ToBinary(lifemValue.Value, buffer); if (lifemValue.Size == ValueSize.DWORD && (count & 0x3) != 0) { uint offset = 4 - (count & 0x3); for (uint i = 0; i < offset; i++) { lifemBinary.Add(0); } count += offset; } else if (lifemValue.Size == ValueSize.WORD && (count & 0x1) != 0) { lifemBinary.Add(0); count += 1; } if (lifemValue.Labels.Any()) { foreach (var label in lifemValue.Labels) { label.RelativeAddress = count; _labels.Add(label); } } switch (lifemValue.Size) { case ValueSize.BYTE: lifemBinary.Add(buffer[3]); count += 1; break; case ValueSize.WORD: lifemBinary.Add(buffer[2]); lifemBinary.Add(buffer[3]); count += 2; break; case ValueSize.DWORD: lifemBinary.Add(buffer[0]); lifemBinary.Add(buffer[1]); lifemBinary.Add(buffer[2]); lifemBinary.Add(buffer[3]); count += 4; break; default: throw new ApplicationException($"Invalid value: {lifemValue.Size}"); } } // コードのバイナリ化 count = 16U; foreach (var code in _codes) { ModRm modrm = code.Modrm; uint value; ToBinary((uint)code.Mnemonic, buffer); binaryCode.Add(buffer[0]); binaryCode.Add(buffer[1]); binaryCode.Add(buffer[2]); binaryCode.Add(buffer[3]); if (code.Head.HasLabel) { switch (modrm.HeadMode) { case OperandMode.REG: modrm.HeadMode = OperandMode.IMM_REG; break; case OperandMode.ADDR_REG: modrm.HeadMode = OperandMode.ADDR_IMM_REG; break; default: break; } } if (code.Tail.HasLabel) { switch (modrm.TailMode) { case OperandMode.REG: modrm.TailMode = OperandMode.IMM_REG; break; case OperandMode.ADDR_REG: modrm.TailMode = OperandMode.ADDR_IMM_REG; break; default: break; } } ToBinary(code.Modrm.Value, buffer); binaryCode.Add(buffer[0]); binaryCode.Add(buffer[1]); binaryCode.Add(buffer[2]); binaryCode.Add(buffer[3]); if ((modrm.HeadMode & (~OperandMode.ADDRESS)) == OperandMode.REG) { value = 0U; } else { value = code.Head.Immidiate; RegisterValue?register = code.Head.First; if (!(register is null) && register.RelativeAddress != 0) { value -= count; } register = code.Head.Second; if (!(register is null) && register.RelativeAddress != 0) { value -= count; } } ToBinary(value, buffer); binaryCode.Add(buffer[0]); binaryCode.Add(buffer[1]); binaryCode.Add(buffer[2]); binaryCode.Add(buffer[3]); if ((modrm.TailMode & (~OperandMode.ADDRESS)) == OperandMode.REG) { value = 0; } else { value = code.Tail.Immidiate; RegisterValue?register = code.Tail.First; if (!(register is null) && register.RelativeAddress != 0) { value -= count; } register = code.Tail.Second; if (!(register is null) && register.RelativeAddress != 0) { value -= count; } } ToBinary(value, buffer); binaryCode.Add(buffer[0]); binaryCode.Add(buffer[1]); binaryCode.Add(buffer[2]); binaryCode.Add(buffer[3]); count += 16; } binaryCode.AddRange(lifemBinary); int length = binaryCode.Count & 0xF; for (int i = 16 - length; i > 0; i--) { binaryCode.Add(0); } return(new ReadOnlyCollection <byte>(binaryCode));