如何在Ruby中实现goto和label方法?
发布时间:2020-12-16 23:14:16 所属栏目:百科 来源:网络整理
导读:作为主题DSL的作业,我需要在 Ruby中编写内联汇编程序.我知道 The Joke Is On Us: How Ruby 1.9 Supports the Goto Statement,但我不能使用它.这是一个非常简单的实现,汇编器有四个寄存器 – ax,bx,cx,dx,保存整数值,我可以在其上做一些操作,比如设置它们的值
作为主题DSL的作业,我需要在
Ruby中编写内联汇编程序.我知道
The Joke Is On Us: How Ruby 1.9 Supports the Goto Statement,但我不能使用它.这是一个非常简单的实现,汇编器有四个寄存器 – ax,bx,cx,dx,保存整数值,我可以在其上做一些操作,比如设置它们的值(mov),比较两个寄存器(cmp),递增a register(inc),跳到某个特定的地方(jmp)和其他一些类别.界面将是这样的:
Asm.asm do mov cx,1 jmp l1 mov ax,1 label l1 mov dx,1 end jmp方法将接受标签名称或其他功能之一的序列号.所以我的问题是:在块中: { mov cx,1 jmp l1 mov ax,1 label l1 mov dx,1 } 如何跟踪当前的功能数量.我的实现看起来大致如下: module Asm def self.asm(&block) memory = Memory.new memory.instance_eval(&block) memory.table.values end class Memory attr_reader :table def initialize @table = { ax: 0,bx: 0,cx: 0,dx: 0 } ... end ... def mov(destination_register,source) ... end def inc(destination_register,value = 1) ... end def dec(destination_register,value = 1) ... end ... end end 我被困在实现jmp aka goto方法.我的一个想法是使用一个哈希来保存所有被调用的方法及其参数,或者循环块,包含指令并根据全局变量中保存的条件执行或不执行方法,但我对此无能为力.因此,例如,有没有办法打破块并将每个指令保存在数组/散列中,然后根据其索引或类似的东西执行它.任何帮助表示赞赏.非常感谢你提前. 解决方法
这是一个想法:预先“解析”汇编代码然后执行它.这包括改变一些事情.这将是我的Memory类的实现:
class Memory attr_reader :table def initialize @table = { ax: 0,dx: 0 } @program = [] @labels = {} end OPS = { "mov" => lambda {|dest,src| @table[dest] = (src.is_a?(Symbol) ? @table[src] : src); nil},"inc" => lambda {|dest,incval = 1| @table[dest] += incval; nil},"jmp" => lambda {|lblname| @labels[lblname]} #and so on } def method_missing(name,*args) if(OPS.keys.include?(name.to_s)) @program << [name.to_s,args] elsif(name.to_s == "label") @labels[args.first] = @program.length else return name end end def load_program(&block) self.instance_exec(&block) end def run_program pc = 0 until(pc == @program.length) instruction = @program[pc] retval = self.instance_exec(*instruction[1],&OPS[instruction[0]]) if(retval) pc = retval else pc += 1 end end end def asm(&block) load_program(&block) run_program @table end end 让我们一步一步来看看.我没有使用每条指令的方法,而是使用lambdas的哈希值.然后,我使用method_missing做三件事: >如果方法名称只是一个随机符号(不是指令名称),我只返回符号.所以现在,cx与:cx相同. 指令lambda的返回值(如果不是nil)用作程序计数器的新值(因此,如果可以添加零,则跳转更多跳转). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |