Disammbler und Simulator angepasst. Arrays begonnen (defunct)
This commit is contained in:
@ -54,6 +54,42 @@ class Program {
|
||||
Console.WriteLine($"CodeLen: {codeLen} bytes");
|
||||
var code = r.ReadBytes(codeLen);
|
||||
|
||||
// Initialize arrays for element type tracking
|
||||
var arrayRanges = new Dictionary<int, (int start, int length, VarType elementType)>();
|
||||
Console.WriteLine("\nAnalyzing variable types:");
|
||||
for (int i = 0; i < nVars; i++) {
|
||||
Console.WriteLine($" [{i}] = {(VarType)varTypes[i]}");
|
||||
}
|
||||
|
||||
Console.WriteLine("\nDetecting arrays:");
|
||||
for (int i = 0; i < nVars; i++) {
|
||||
if (varTypes[i] == (byte)VarType.ARRAY && i + 2 <= nVars) {
|
||||
// An array consists of:
|
||||
// - ARRAY marker at position i
|
||||
// - ElementType at position i+1
|
||||
// - Array elements starting at position i+2
|
||||
int arrayStart = i;
|
||||
VarType elementType = (VarType)varTypes[i + 1];
|
||||
int startOfElements = i + 2;
|
||||
|
||||
// Count elements until we hit either end of vars or a different type
|
||||
int length = 0;
|
||||
for (int j = startOfElements; j < nVars; j++) {
|
||||
if (varTypes[j] != (byte)elementType) break;
|
||||
length++;
|
||||
}
|
||||
|
||||
arrayRanges[arrayStart] = (startOfElements, length, elementType);
|
||||
Console.WriteLine($"Found array at index {arrayStart}:");
|
||||
Console.WriteLine($" - Element type: {elementType}");
|
||||
Console.WriteLine($" - Elements start at: {startOfElements}");
|
||||
Console.WriteLine($" - Length: {length}");
|
||||
|
||||
// Skip past the array definition (ARRAY marker + element type)
|
||||
i = startOfElements - 1;
|
||||
}
|
||||
}
|
||||
|
||||
var stack = new Stack<object>();
|
||||
var vars = new object[nVars];
|
||||
int ip = 0;
|
||||
@ -61,7 +97,7 @@ class Program {
|
||||
while (ip < code.Length) {
|
||||
int addr = ip;
|
||||
byte op = code[ip++];
|
||||
Console.Write($"{addr:0000}: 0x{op:X2} {Bytecode.OpName(op)} ");
|
||||
Console.Write($"{addr:0000}: 0x{op:X2} ");
|
||||
switch (op) {
|
||||
case Bytecode.OpCodes.NOP: Console.WriteLine("NOP"); break;
|
||||
case Bytecode.OpCodes.PUSH_CONST: {
|
||||
@ -76,12 +112,103 @@ class Program {
|
||||
Console.WriteLine($"PUSH_REAL_CONST {ci} ({consts[ci]})");
|
||||
stack.Push(consts[ci]);
|
||||
break; }
|
||||
case Bytecode.OpCodes.LOAD_VAR: { ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"LOAD_VAR {vi}"); stack.Push(vars[vi]); break; }
|
||||
case Bytecode.OpCodes.STORE_VAR: { ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"STORE_VAR {vi}"); vars[vi] = stack.Pop(); break; }
|
||||
case Bytecode.OpCodes.JZ: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JZ addr={target}"); var cond = stack.Pop(); bool isFalse = cond is int ci ? ci == 0 : cond is long cl ? cl == 0L : cond is double cd ? cd == 0.0 : cond == null; if (isFalse) ip = target; break; }
|
||||
case Bytecode.OpCodes.JMP: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JMP addr={target}"); ip = target; break; }
|
||||
case Bytecode.OpCodes.HALT: Console.WriteLine("HALT"); ip = code.Length; break;
|
||||
default: Console.WriteLine();
|
||||
case Bytecode.OpCodes.LOAD_VAR: {
|
||||
ushort vi = (ushort)(code[ip++] | (code[ip++] << 8));
|
||||
Console.WriteLine($"LOAD_VAR {vi}");
|
||||
|
||||
// Check if the variable index is within bounds
|
||||
if (vi >= vars.Length) {
|
||||
throw new Exception($"Variable index {vi} is out of bounds (max: {vars.Length - 1})");
|
||||
}
|
||||
|
||||
if (arrayRanges.ContainsKey(vi)) {
|
||||
var (start, arrayLength, arrayElementType) = arrayRanges[vi];
|
||||
var arrayData = new object[arrayLength];
|
||||
Array.Copy(vars, start, arrayData, 0, arrayLength);
|
||||
stack.Push(arrayData);
|
||||
} else {
|
||||
stack.Push(vars[vi]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Bytecode.OpCodes.STORE_VAR: {
|
||||
ushort vi = (ushort)(code[ip++] | (code[ip++] << 8));
|
||||
Console.WriteLine($"STORE_VAR {vi}");
|
||||
|
||||
// Check if the variable index is within bounds
|
||||
if (vi >= vars.Length) {
|
||||
throw new Exception($"Variable index {vi} is out of bounds (max: {vars.Length - 1})");
|
||||
}
|
||||
|
||||
var value = stack.Pop();
|
||||
if (arrayRanges.ContainsKey(vi)) {
|
||||
var (start, arrayLength, arrayElementType) = arrayRanges[vi];
|
||||
if (value is object[] arr) {
|
||||
Array.Copy(arr, 0, vars, start, Math.Min(arr.Length, arrayLength));
|
||||
} else {
|
||||
Console.WriteLine($"Warning: Attempting to store non-array value in array variable at index {vi}");
|
||||
vars[vi] = value;
|
||||
}
|
||||
} else {
|
||||
vars[vi] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Bytecode.OpCodes.JZ: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JZ addr={target:0000}"); var cond = stack.Pop(); bool isFalse = cond is int ci ? ci == 0 : cond is long cl ? cl == 0L : cond is double cd ? cd == 0.0 : cond == null; if (isFalse) ip = target; break; }
|
||||
case Bytecode.OpCodes.JMP: {
|
||||
ushort target = (ushort)(code[ip++] | (code[ip++] << 8));
|
||||
Console.WriteLine($"JMP addr={target:0000}");
|
||||
ip = target;
|
||||
break;
|
||||
}
|
||||
case Bytecode.OpCodes.HALT:
|
||||
Console.WriteLine("HALT");
|
||||
ip = code.Length;
|
||||
break;
|
||||
case Bytecode.OpCodes.ARRAY_BOUNDS_CHECK:
|
||||
// Extract the array index from the instruction
|
||||
byte arrayIndex = 0;
|
||||
if (ip < code.Length) {
|
||||
arrayIndex = code[ip];
|
||||
ip++;
|
||||
}
|
||||
|
||||
// Check if this variable is actually an array
|
||||
if (!arrayRanges.ContainsKey(arrayIndex)) {
|
||||
Console.WriteLine($"Warning: ARRAY_BOUNDS_CHECK instruction for non-array variable {arrayIndex}");
|
||||
continue; // Skip this instruction
|
||||
}
|
||||
|
||||
Console.WriteLine($"ARRAY_BOUNDS_CHECK for array at index {arrayIndex}");
|
||||
|
||||
if (stack.Count < 1) {
|
||||
throw new Exception("Stack underflow during array bounds check");
|
||||
}
|
||||
|
||||
// Convert index value safely
|
||||
var indexObj = stack.Pop();
|
||||
int index = Convert.ToInt32(indexObj);
|
||||
|
||||
// The arrayStart from the instruction should be the array marker directly
|
||||
if (!arrayRanges.TryGetValue(arrayIndex, out var arrayInfo)) {
|
||||
// This should not happen since we checked above
|
||||
throw new Exception($"Array metadata missing for index {arrayIndex}");
|
||||
}
|
||||
|
||||
var (elementsStart, length, elementType) = arrayInfo;
|
||||
|
||||
// Adjust for IEC array indexing (1-based)
|
||||
int adjustedIndex = index - 1;
|
||||
if (adjustedIndex < 0 || adjustedIndex >= length) {
|
||||
throw new Exception($"Array index {index} out of bounds [1..{length}]");
|
||||
}
|
||||
|
||||
// Calculate the actual element address
|
||||
stack.Push(elementsStart + adjustedIndex);
|
||||
Console.WriteLine($"Accessing element {index} of array, mapped to variable index {elementsStart + adjustedIndex}");
|
||||
break;
|
||||
default:
|
||||
;
|
||||
// fallback handlers
|
||||
if (Bytecode.OpName(op).StartsWith("ADD_") || Bytecode.OpName(op).StartsWith("SUB_") || Bytecode.OpName(op).StartsWith("MUL_") || Bytecode.OpName(op).StartsWith("DIV_")) {
|
||||
dynamic b = stack.Pop(); dynamic a = stack.Pop(); if (Bytecode.OpName(op).StartsWith("ADD_")) stack.Push(a + b); else if (Bytecode.OpName(op).StartsWith("SUB_")) stack.Push(a - b); else if (Bytecode.OpName(op).StartsWith("MUL_")) stack.Push(a * b); else stack.Push(a / b);
|
||||
@ -98,6 +225,47 @@ class Program {
|
||||
stack.Push(res ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
// Array operations
|
||||
if (op == Bytecode.OpCodes.ARRAY_BOUNDS_CHECK) {
|
||||
// Extract the array index from the instruction
|
||||
byte arrayIndexInner = 0;
|
||||
if (ip < code.Length) {
|
||||
arrayIndexInner = code[ip];
|
||||
ip++;
|
||||
}
|
||||
|
||||
// Check if this variable is actually an array
|
||||
if (!arrayRanges.ContainsKey(arrayIndexInner)) {
|
||||
Console.WriteLine($"Warning: ARRAY_BOUNDS_CHECK instruction for non-array variable {arrayIndexInner}");
|
||||
continue; // Skip this instruction
|
||||
}
|
||||
|
||||
Console.WriteLine($"ARRAY_BOUNDS_CHECK for array at index {arrayIndexInner}");
|
||||
|
||||
if (stack.Count < 1) {
|
||||
throw new Exception("Stack underflow during array bounds check");
|
||||
}
|
||||
|
||||
// Convert index value safely
|
||||
var indexObjInner = stack.Pop();
|
||||
int indexInner = Convert.ToInt32(indexObjInner);
|
||||
|
||||
// The arrayStart from the instruction should be the array marker directly
|
||||
if (!arrayRanges.TryGetValue(arrayIndexInner, out var arrayInfoInner)) {
|
||||
// This should not happen since we checked above
|
||||
throw new Exception($"Array metadata missing for index {arrayIndexInner}");
|
||||
}
|
||||
|
||||
var (elementsStartInner, lengthInner, elementTypeInner) = arrayInfoInner;
|
||||
if (indexInner < 0 || indexInner >= lengthInner) {
|
||||
throw new Exception($"Array index {indexInner} out of bounds [0..{lengthInner-1}]");
|
||||
}
|
||||
|
||||
// Calculate the actual element address
|
||||
stack.Push(elementsStartInner + indexInner);
|
||||
Console.WriteLine($"Accessing element {indexInner} of array, mapped to variable index {elementsStartInner + indexInner}");
|
||||
break;
|
||||
}
|
||||
throw new Exception($"Unknown opcode 0x{op:X2}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user