# # Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode. # # Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com) # # This file is part of Ronin ASM. # # Ronin is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ronin is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ronin. If not, see <http://www.gnu.org/licenses/> # require 'ronin/asm/syntax/common' module Ronin module ASM module Syntax class Intel < Common # Data sizes and their identifiers WIDTHS = { 1 => 'BYTE', 2 => 'WORD', 4 => 'DWORD', 8 => 'QWORD' } # # Emits a register. # # @param [Register] reg # The register. # # @return [String] # The register name. # def self.emit_register(reg) reg.name.to_s end # # Emits an immediate operand. # # @param [ImmediateOperand] op # The operand. # # @return [String] # The formatted immediate operand. # def self.emit_immediate_operand(op) "#{WIDTHS[op.width]} #{emit_integer(op.value)}" end # # Emits a memory operand. # # @param [MemoryOperand] op # The operand. # # @return [String] # The formatted memory operand. # def self.emit_memory_operand(op) asm = emit_register(op.base) if op.index asm << '+' << emit_register(op.index) asm << '*' << emit_integer(op.scale) if op.scale > 1 end if op.offset != 0 sign = if op.offset >= 0 then '+' else '-' end asm << sign << emit_integer(op.offset) end return "[#{asm}]" end # # Emits multiple operands. # # @param [Array<ImmediateOperand, MemoryOperand, Register, Symbol>] ops # The Array of operands. # # @return [String] # The formatted operands. # def self.emit_operands(ops) if ops.length > 1 [ops[-1], *ops[0..-2]].map { |op| emit_operand(op) }.join(",\t") else super(ops) end end # # Emits an instruction. # # @param [Instruction] ins # The instruction. # # @return [String] # The formatted instruction. # def self.emit_instruction(ins) line = emit_keyword(ins.name) unless ins.operands.empty? line << "\t" << emit_operands(ins.operands) end return line end # # Emits a program. # # @param [Program] program # The program. # # @return [String] # The formatted program. # def self.emit_program(program) asm = super(program) # prepend the `BITS 64` directive for YASM if program.arch == :amd64 asm = ["BITS 64", '', asm].join($/) end return asm end end end end end