Add Segment Register command, add Modeline, &c
This commit is contained in:
parent
ef98f1e243
commit
8e8f85fc53
4 changed files with 85 additions and 41 deletions
|
@ -10,6 +10,7 @@ The intent behind this project--beyond learning x86 assembly--is to fully emulat
|
|||
Currently there are no dependencies for Miharu. To build and run the CLI REPL, simply:
|
||||
|
||||
#+begin_src shell
|
||||
guix shell --pure -m=manifest.scm
|
||||
zig build run
|
||||
#+end_src
|
||||
|
||||
|
@ -33,5 +34,7 @@ Type `?` for help.
|
|||
Type `exit` to quit.
|
||||
>
|
||||
#+end_src
|
||||
* Links
|
||||
* References
|
||||
- [[http://www.c-jump.com/CIS77/reference/Instructions_by_Opcode.html][Opcode Reference]]
|
||||
- [[https://pdos.csail.mit.edu/archive/6.097/readings/intelv2.pdf][Intel Reference Manual]]
|
||||
- [[https://en.wikipedia.org/wiki/X86_instruction_listings][x86 Instructions By Architecture]]
|
||||
|
|
23
src/cpu.zig
23
src/cpu.zig
|
@ -19,9 +19,9 @@ const mem = @import("memory.zig");
|
|||
|
||||
pub const Register = enum {
|
||||
EAX,
|
||||
EBX,
|
||||
ECX,
|
||||
EDX,
|
||||
EBX,
|
||||
//
|
||||
ESP,
|
||||
EBP,
|
||||
|
@ -29,10 +29,27 @@ pub const Register = enum {
|
|||
EDI,
|
||||
};
|
||||
|
||||
pub const SegmentRegister = enum {
|
||||
CS,
|
||||
DS,
|
||||
SS,
|
||||
ES,
|
||||
FS,
|
||||
GS,
|
||||
};
|
||||
|
||||
pub const Cpu = struct {
|
||||
registers: std.EnumArray(Register, u32),
|
||||
segmentRegisters: std.EnumArray(SegmentRegister, u16),
|
||||
instruction_pointer: u32, //EIP
|
||||
pub fn execute(self: *Cpu, memory: *mem.Memory, opcode: u8, reg1: Register, reg2: Register) void {
|
||||
switch (opcode) {}
|
||||
|
||||
pub fn init() Cpu {
|
||||
return Cpu{
|
||||
.instruction_pointer = 0,
|
||||
.segmentRegisters = std.EnumArray(SegmentRegister, u16)
|
||||
.initFill(0x0000),
|
||||
.registers = std.EnumArray(Register, u32)
|
||||
.initFill(0x00000000),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -44,9 +44,18 @@ pub const Instruction = struct {
|
|||
};
|
||||
|
||||
pub const Opcode = enum {
|
||||
/// Move family
|
||||
//
|
||||
MovRegToRegMem_8 = 0x88,
|
||||
MovRegToRegMem_16_32 = 0x89,
|
||||
MovRegMemToMem_8 = 0x8A,
|
||||
MovRegMemToReg_16_32 = 0xBB,
|
||||
MovRegMemToReg_16_32 = 0x8B,
|
||||
MovRegMemToSeg_16 = 0x8C,
|
||||
LoadEffectiveAddr_16_32 = 0x8D,
|
||||
MovMemToSeg_16 = 0x8E,
|
||||
//
|
||||
JmpNear_16_32 = 0xE9,
|
||||
JmpFar_16_32 = 0xEA,
|
||||
JmpShort_8 = 0xEB,
|
||||
//
|
||||
MultiByte = 0xFF,
|
||||
};
|
||||
|
|
75
src/main.zig
75
src/main.zig
|
@ -16,9 +16,11 @@
|
|||
|
||||
const std = @import("std");
|
||||
const mem = @import("memory.zig");
|
||||
const cpu_ = @import("cpu.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
var memory = mem.Memory.init();
|
||||
var cpu = cpu_.Cpu.init();
|
||||
var input = std.io.getStdIn().reader();
|
||||
var output = std.io.getStdOut().writer();
|
||||
//Switch to new buffer
|
||||
|
@ -41,15 +43,15 @@ pub fn main() !void {
|
|||
, .{});
|
||||
var buffer: [256]u8 = undefined;
|
||||
while (true) {
|
||||
std.debug.print("> ", .{});
|
||||
modeLine(&cpu, &memory);
|
||||
const line = try input.readUntilDelimiterOrEof(&buffer, '\n');
|
||||
const clean = std.mem.trim(u8, line.?, " \n\r");
|
||||
var it = std.mem.splitSequence(u8, clean, " ");
|
||||
if (it.next()) |first_argument| {
|
||||
if (std.mem.eql(u8, first_argument, "exit")) {
|
||||
break;
|
||||
} else if (std.mem.eql(u8, first_argument, "mem")) {
|
||||
try handleMemoryCommand(&memory, &it);
|
||||
} else if (std.mem.eql(u8, first_argument, "sr")) {
|
||||
try handleSegmentRegisterCommand(&cpu, &it);
|
||||
}
|
||||
} else {
|
||||
// noop
|
||||
|
@ -62,37 +64,50 @@ pub fn main() !void {
|
|||
_ = try output.writeAll("\x1b[?25h");
|
||||
}
|
||||
|
||||
fn handleMemoryCommand(memory: *mem.Memory, it: anytype) !void {
|
||||
if (it.next()) |next_argument| {
|
||||
if (std.mem.eql(u8, next_argument, "read")) {
|
||||
if (it.next()) |address| {
|
||||
const addr = try std.fmt.parseUnsigned(u8, address, 10);
|
||||
const value = try memory.readByte(addr);
|
||||
fn modeLine(cpu: *cpu_.Cpu, memory: *mem.Memory) void {
|
||||
_ = memory;
|
||||
std.debug.print(
|
||||
\\MEM @ {}: {}
|
||||
\\
|
||||
, .{ addr, value });
|
||||
}
|
||||
} else if (std.mem.eql(u8, next_argument, "write")) {
|
||||
const maybe_addr = it.next();
|
||||
const maybe_value = it.next();
|
||||
if (maybe_addr == null or maybe_value == null) {
|
||||
\\IP : {x:0>8}
|
||||
\\EAX: {x:0>8} EBX: {x:0>8} ECX: {x:0>8} EDX: {x:0>8}
|
||||
\\ESP: {x:0>8} EBP: {x:0>8} ESI: {x:0>8} EDI: {x:0>8}
|
||||
\\
|
||||
, .{
|
||||
cpu.instruction_pointer,
|
||||
cpu.registers.get(.EAX),
|
||||
cpu.registers.get(.EBX),
|
||||
cpu.registers.get(.ECX),
|
||||
cpu.registers.get(.EDX),
|
||||
//
|
||||
cpu.registers.get(.ESP),
|
||||
cpu.registers.get(.EBP),
|
||||
cpu.registers.get(.ESI),
|
||||
cpu.registers.get(.EDI),
|
||||
});
|
||||
std.debug.print("> ", .{});
|
||||
}
|
||||
|
||||
fn printSr(cpu: *cpu_.Cpu) void {
|
||||
std.debug.print(
|
||||
\\Invalid arguments. Usage: mem write <addr> <value>
|
||||
\\Segment Registers:
|
||||
\\CS: {x:0>4} DS: {x:0>4} SS: {x:0>4}
|
||||
\\ES: {x:0>4} FS: {x:0>4} GS: {x:0>4}
|
||||
\\
|
||||
, .{});
|
||||
, .{
|
||||
cpu.segmentRegisters.get(.CS),
|
||||
cpu.segmentRegisters.get(.DS),
|
||||
cpu.segmentRegisters.get(.SS),
|
||||
//
|
||||
cpu.segmentRegisters.get(.ES),
|
||||
cpu.segmentRegisters.get(.FS),
|
||||
cpu.segmentRegisters.get(.GS),
|
||||
});
|
||||
}
|
||||
|
||||
fn handleSegmentRegisterCommand(cpu: *cpu_.Cpu, it: anytype) !void {
|
||||
if (it.next()) |_| {
|
||||
std.debug.print("Wrong number of arguments.\n", .{});
|
||||
} else {
|
||||
const addr = try std.fmt.parseUnsigned(u8, maybe_addr.?, 10);
|
||||
const value = try std.fmt.parseUnsigned(u8, maybe_value.?, 10);
|
||||
_ = try memory.writeByte(addr, value);
|
||||
}
|
||||
} else {
|
||||
std.debug.print(
|
||||
\\Invalid argument '{s}'. Usage:
|
||||
\\ mem read <addr>
|
||||
\\ mem write <adrr> <value>
|
||||
\\
|
||||
, .{next_argument});
|
||||
}
|
||||
printSr(cpu);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue