8086 simulator in ruby

I’m thinking of writing a simulator for the intel 8086 processor in
ruby. At first I’m interested in implementing basic instruction
execution and memory access, no interrupts. The interface may later be
implemented with Tk maybe even as an ajax application on rails. My buest
guess is using metaprogramming for interpreting the assembly
instructions. I’m not wery experienced with design patterns, so I need
some ideas on the levels of abstraction (the classes) i need to start
with this. Any ideas?

Vasil V. wrote:

I’m thinking of writing a simulator for the intel 8086 processor in
ruby. At first I’m interested in implementing basic instruction
execution and memory access, no interrupts. The interface may later be
implemented with Tk maybe even as an ajax application on rails. My buest
guess is using metaprogramming for interpreting the assembly
instructions. I’m not wery experienced with design patterns, so I need
some ideas on the levels of abstraction (the classes) i need to start
with this. Any ideas?

Woo-hoo! Like Larry Wall said (he’d know), Real programmers can write
assembler in any language!

Try:

cpu = CPU.new
cpu.push 42
cpu.shift :b

and away you go!

(Oh, and use Test Driven Development to write it all. I think that’s
generally how Intel invents chips, too!)

On 8/17/07, Vasil V. [email protected] wrote:

I’m thinking of writing a simulator for the intel 8086 processor in
ruby. At first I’m interested in implementing basic instruction
execution and memory access, no interrupts. The interface may later be
implemented with Tk maybe even as an ajax application on rails. My buest
guess is using metaprogramming for interpreting the assembly
instructions. I’m not wery experienced with design patterns, so I need
some ideas on the levels of abstraction (the classes) i need to start
with this. Any ideas?

Check out rubinius at http://rubini.us for a Ruby implementation
written (mostly) in Ruby and (mostly) test-first. It may help you
think of some ideas.

What you are describing is basically just a virtual machine that you
happen to already know the V-ISA for. You can definitely do this in
Ruby, though simulating a real CPU is never going to be easy.

Aww, how about a C-64 emulator…
you could even offer an option to simulate “speed” when loading from
“tape”
(avg time: 30 - 60min, chance of failure: 65% or higher)
Or even a PDP-11

Just be sure to include the frustrations of old, slow machines that
often had problems, as an option to set. Can be very instructional to
users who never had the experience and to those who start to wax
nostalgic.

John J. wrote:

Aww, how about a C-64 emulator…
you could even offer an option to simulate “speed” when loading from
“tape”
(avg time: 30 - 60min, chance of failure: 65% or higher)
Or even a PDP-11

Dude, there are simulations of Ada & Babbage’s “Inference Engine” out
there!

On 8/17/07, Vasil V. [email protected] wrote:

I do not think metaprogramming is of use here, maybe you can get some
inspiration from here?
http://www.rubyquiz.com/quiz88.html
HTH
Robert

Robert K. wrote:

CPU8086 do
label :begin
push 42
shift :b
jmp :begin
end

How you get a class name to respond to do? I thought objects couldn’t
respond to do, essentially at the syntax level…

(Or is that pseudo?)

On 17.08.2007 21:41, Phlip wrote:

Woo-hoo! Like Larry Wall said (he’d know), Real programmers can write
assembler in any language!

Try:

cpu = CPU.new
cpu.push 42
cpu.shift :b

and away you go!

I’d rather do

CPU8086 do
label :begin
push 42
shift :b
jmp :begin
end

I.e. create an instance behind the scenes and instance_eval the block.

Kind regards

robert

Phlip wrote:

How you get a class name to respond to do? I thought objects couldn’t
respond to do, essentially at the syntax level…

(Or is that pseudo?)

def FOO
yield
end

FOO do
puts ‘FOO called’
end

=> FOO called


Tom Preston-Werner

On Aug 17, 2007, at 5:00 PM, Phlip wrote:

respond to do, essentially at the syntax level…

(Or is that pseudo?)

Nah, it’s just a normal block of Ruby!
With an iterator, you might do:

10.times do
puts ‘hello’
end

In this case, 10 is not really any different than CPU8086.
Think of do-end as a block that iterates 1 time. That’s what it is!

Aww, how about a C-64 emulator…
you could even offer an option to simulate “speed” when loading from
“tape”
(avg time: 30 - 60min, chance of failure: 65% or higher)

Brings to mind the old punchline about that Commodore tape drive:
Records
data faster than you can type it in!

Try:

  cpu = CPU.new
  cpu.push 42
  cpu.shift :b

and away you go!

Actually, even though this example may be totally useless (although it
contains the ultimate answer to everything!), I really really love the
abstraction you can get. Would be funny to write in ruby but get
compiled assembler code!

Wouldnt using cpu << 42 be nicer though? :smiley:

Nice idea Vasil.
8086 simulator as a DSL in ruby is a very good idea.
I would just love to see your implementation

Rubini.us etc are different things.

bye :slight_smile:
Ashish
[email protected]

Think of do-end as a block that iterates 1 time. That’s what it is!

Please read my posting history, blogs, Ruby open source, etc. (-;

Robert K. wrote:

Actually it’s not the “10” but the “times” because “CPU8086” would be a
method.

def CPU8086(&b)

The point: I thought a method was forbidden as a constant. Easy to write
but
hard to call.

By contrast…

doc = Hpricot(my_html_string)

His Whyness did something to the module to make it take a method call
directly…

On 18.08.2007 04:45, John J. wrote:

end
10.times do
puts ‘hello’
end

In this case, 10 is not really any different than CPU8086.
Think of do-end as a block that iterates 1 time. That’s what it is!

Actually it’s not the “10” but the “times” because “CPU8086” would be a
method.

def CPU8086(&b)
o = Whatever.new
o.instance_eval(&b)
end

Kind regards

robert

On 8/18/07, Phlip [email protected] wrote:

The point: I thought a method was forbidden as a constant. Easy to write but
hard to call.

By contrast…

doc = Hpricot(my_html_string)

His Whyness did something to the module to make it take a method call
directly…

No modules were hacked or harmed. He just defined a method:

3 def Hpricot(input = nil, opts = {}, &blk)
4 Hpricot.parse(input, opts, &blk)
5 end

http://code.whytheluckystiff.net/hpricot/browser/trunk/lib/hpricot/parse.rb

On Aug 18, 2007, at 9:24 AM, Chris C. wrote:

His Whyness did something to the module to make it take a method call
parse.rb


Chris C.
concentrationstudios.com
brynmawrcs.com

Yep, normal stuff. EXCEPT for the capitalization. You can do it, but
it goes against usual style.
An example:

module Unchi

def poots(who)
puts “#{who} did pooh, poot”
end

Poots = poots

alias_method :Poots, :poots

end
include Unchi

Poots(“JJ”)

On 18.08.2007 17:04, John J. wrote:

Actually it’s not the “10” but the “times” because “CPU8086” would be a
method.

def CPU8086(&b)

The point: I thought a method was forbidden as a constant. Easy to
write but
hard to call.

Phlip, not sure what you meant by this. It’s not different from any
other method.

3 def Hpricot(input = nil, opts = {}, &blk)
4 Hpricot.parse(input, opts, &blk)
5 end

http://code.whytheluckystiff.net/hpricot/browser/trunk/lib/hpricot/parse.rb

Yep, normal stuff. EXCEPT for the capitalization. You can do it, but it
goes against usual style.

Even the std lib does it:

irb(main):019:0> Kernel.methods.grep /^[A-Z]/
=> [“Integer”, “Float”, “String”, “Array”]

I don’t see a big issue here.

Kind regards

robert

I’m thinking of writing a simulator for the intel 8086 processor in
ruby. At first I’m interested in implementing basic instruction
execution and memory access, no interrupts. The interface may later be
implemented with Tk maybe even as an ajax application on rails. My buest
guess is using metaprogramming for interpreting the assembly
instructions. I’m not wery experienced with design patterns, so I need
some ideas on the levels of abstraction (the classes) i need to start
with this. Any ideas?

That depends on the level of emulation you want. What others propose
here seems to be a quite high level assembler interpreter.

A CPU bascically operates on memory and has several registers, one being
the instruction pointer.

So on some no-exact-timing, debugger-like level you implement just that:
Memory can be an array or a string[1]. At each step the byte at the ip
is read, decoded and the ip incremented until you have a full
instruction, referenced memory is read, instruction executed and the
result stored in memory or a register.

class CPU8086
attr_accessor :memory, :ip, :sp, :ax, :bc, :cx …

The instruction manual basically describes the interface.

mfg, simon … l

[1] Is there a performing byte storage in Ruby 1.9?

Robert K. wrote:

def CPU8086(&b)

The point: I thought a method was forbidden as a constant. Easy to write
but
hard to call.

Phlip, not sure what you meant by this. It’s not different from any other
method.

I mis-remembered something. Something about a method that you could
create
but would have difficulty calling. No worries.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs