ronin-code-asm 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.editorconfig +11 -0
  4. data/.github/workflows/ruby.yml +31 -0
  5. data/.gitignore +11 -0
  6. data/.mailmap +1 -0
  7. data/.rspec +1 -0
  8. data/.ruby-version +1 -0
  9. data/.yardopts +1 -0
  10. data/COPYING.txt +165 -0
  11. data/ChangeLog.md +44 -0
  12. data/Gemfile +25 -0
  13. data/README.md +166 -0
  14. data/Rakefile +39 -0
  15. data/data/os/freebsd/amd64/syscalls.yml +415 -0
  16. data/data/os/freebsd/x86/syscalls.yml +415 -0
  17. data/data/os/linux/amd64/syscalls.yml +306 -0
  18. data/data/os/linux/x86/syscalls.yml +339 -0
  19. data/gemspec.yml +26 -0
  20. data/lib/ronin/code/asm/archs/amd64.rb +100 -0
  21. data/lib/ronin/code/asm/archs/x86.rb +170 -0
  22. data/lib/ronin/code/asm/archs.rb +22 -0
  23. data/lib/ronin/code/asm/config.rb +33 -0
  24. data/lib/ronin/code/asm/immediate_operand.rb +84 -0
  25. data/lib/ronin/code/asm/instruction.rb +66 -0
  26. data/lib/ronin/code/asm/memory_operand.rb +119 -0
  27. data/lib/ronin/code/asm/os/freebsd.rb +35 -0
  28. data/lib/ronin/code/asm/os/linux.rb +35 -0
  29. data/lib/ronin/code/asm/os/os.rb +47 -0
  30. data/lib/ronin/code/asm/os.rb +57 -0
  31. data/lib/ronin/code/asm/program.rb +509 -0
  32. data/lib/ronin/code/asm/register.rb +111 -0
  33. data/lib/ronin/code/asm/shellcode.rb +75 -0
  34. data/lib/ronin/code/asm/syntax/att.rb +164 -0
  35. data/lib/ronin/code/asm/syntax/common.rb +241 -0
  36. data/lib/ronin/code/asm/syntax/intel.rb +150 -0
  37. data/lib/ronin/code/asm/syntax.rb +22 -0
  38. data/lib/ronin/code/asm/version.rb +28 -0
  39. data/lib/ronin/code/asm.rb +68 -0
  40. data/ronin-code-asm.gemspec +62 -0
  41. data/spec/asm_spec.rb +14 -0
  42. data/spec/config_spec.rb +10 -0
  43. data/spec/immediate_operand_spec.rb +79 -0
  44. data/spec/instruction_spec.rb +62 -0
  45. data/spec/memory_operand_spec.rb +80 -0
  46. data/spec/os_spec.rb +68 -0
  47. data/spec/program_spec.rb +439 -0
  48. data/spec/register_spec.rb +112 -0
  49. data/spec/shellcode_spec.rb +58 -0
  50. data/spec/spec_helper.rb +7 -0
  51. data/spec/syntax/att_spec.rb +181 -0
  52. data/spec/syntax/common_spec.rb +42 -0
  53. data/spec/syntax/intel_spec.rb +174 -0
  54. metadata +143 -0
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-code-asm - A Ruby DSL for crafting Assembly programs and shellcode.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-code-asm is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-code-asm is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-code-asm. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/code/asm/config'
22
+
23
+ require 'yaml'
24
+
25
+ module Ronin
26
+ module Code
27
+ module ASM
28
+ module OS
29
+ #
30
+ # Collection of all known syscalls, grouped by OS and Arch.
31
+ #
32
+ # @return [Hash{Symbol => Hash{Symbol => Hash{Symbol => Integer}}}]
33
+ # Syscall names and numbers, organized by OS then Arch.
34
+ #
35
+ # @api private
36
+ #
37
+ SYSCALLS = Hash.new do |hash,os|
38
+ hash[os] = Hash.new do |subhash,arch|
39
+ subhash[arch] = YAML.load_file(
40
+ File.join(Config::DATA_DIR,'os',os.to_s.downcase,arch.to_s,'syscalls.yml')
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-code-asm - A Ruby DSL for crafting Assembly programs and shellcode.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-code-asm is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-code-asm is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-code-asm. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/code/asm/os/os'
22
+ require 'ronin/code/asm/os/freebsd'
23
+ require 'ronin/code/asm/os/linux'
24
+
25
+ module Ronin
26
+ module Code
27
+ module ASM
28
+ module OS
29
+ # The mapping of OS names to modules.
30
+ NAMES = {
31
+ linux: Linux,
32
+ freebsd: FreeBSD
33
+ }
34
+
35
+ #
36
+ # Fetches the OS module with the given name.
37
+ #
38
+ # @param [Symbol] name
39
+ # The OS name (ex: `:linux`).
40
+ #
41
+ # @return [Linux, FreeBSD]
42
+ # The OS module.
43
+ #
44
+ # @raise [ArgumentError]
45
+ # The OS name was unknown.
46
+ #
47
+ # @since 1.0.0
48
+ #
49
+ def self.[](name)
50
+ NAMES.fetch(name) do
51
+ raise(ArgumentError,"unknown OS name: #{name.inspect}")
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,509 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-code-asm - A Ruby DSL for crafting Assembly programs and shellcode.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-code-asm is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-code-asm is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-code-asm. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/code/asm/archs'
22
+ require 'ronin/code/asm/os'
23
+ require 'ronin/code/asm/register'
24
+ require 'ronin/code/asm/instruction'
25
+ require 'ronin/code/asm/immediate_operand'
26
+ require 'ronin/code/asm/syntax'
27
+
28
+ require 'tempfile'
29
+ require 'yasm/program'
30
+
31
+ module Ronin
32
+ module Code
33
+ module ASM
34
+ #
35
+ # Represents a full Assembly program.
36
+ #
37
+ class Program
38
+
39
+ # Supported Assembly Syntaxs
40
+ SYNTAX = {
41
+ att: Syntax::ATT,
42
+ intel: Syntax::Intel
43
+ }
44
+
45
+ # The Assembly Parsers
46
+ PARSERS = {
47
+ att: :gas,
48
+ intel: :nasm
49
+ }
50
+
51
+ # The targeted architecture
52
+ #
53
+ # @return [Symbol]
54
+ attr_reader :arch
55
+
56
+ # The targeted Operating System
57
+ #
58
+ # @return [Symbol, nil]
59
+ attr_reader :os
60
+
61
+ # The default word size
62
+ #
63
+ # @return [Integer]
64
+ attr_reader :word_size
65
+
66
+ # The registers available to the program
67
+ #
68
+ # @return [Hash{Symbol => Register}]
69
+ # The names and registers.
70
+ attr_reader :registers
71
+
72
+ # The syscalls available to the program
73
+ #
74
+ # @return [Hash{Symbol => Integer}]
75
+ # The syscall names and numbers.
76
+ attr_reader :syscalls
77
+
78
+ # The registers used by the program
79
+ #
80
+ # @return [Array<Symbol>]
81
+ attr_reader :allocated_registers
82
+
83
+ # The instructions of the program
84
+ #
85
+ # @return [Array<Instruction>]
86
+ attr_reader :instructions
87
+
88
+ #
89
+ # Initializes a new Assembly Program.
90
+ #
91
+ # @param [Symbol] arch
92
+ # The Architecture to target.
93
+ #
94
+ # @param [Symbol, nil] os
95
+ # The Operating System to target.
96
+ #
97
+ # @param [Hash{Symbol => Object}] define
98
+ # Constants to define in the program.
99
+ #
100
+ # @yield []
101
+ # The given block will be evaluated within the program.
102
+ #
103
+ # @example
104
+ # Program.new(arch: :amd64) do
105
+ # push rax
106
+ # push rbx
107
+ #
108
+ # mov rsp, rax
109
+ # mov rax[8], rbx
110
+ # end
111
+ #
112
+ def initialize(arch: :x86, os: nil, define: {}, &block)
113
+ @arch = arch
114
+
115
+ arch = Archs.const_get(@arch.to_s.upcase)
116
+
117
+ @word_size = arch::WORD_SIZE
118
+ @registers = arch::REGISTERS
119
+
120
+ extend arch
121
+
122
+ @syscalls = {}
123
+
124
+ if os
125
+ @os = os
126
+ @syscalls = OS::SYSCALLS[@os][@arch]
127
+
128
+ extend OS[@os]
129
+ end
130
+
131
+ define.each do |name,value|
132
+ instance_variable_set("@#{name}",value)
133
+ end
134
+
135
+ @allocated_registers = []
136
+ @instructions = []
137
+
138
+ instance_eval(&block) if block
139
+ end
140
+
141
+ #
142
+ # Determines if a register exists.
143
+ #
144
+ # @param [Symbol] name
145
+ # The name of the register.
146
+ #
147
+ # @return [Boolean]
148
+ # Specifies whether the register exists.
149
+ #
150
+ def register?(name)
151
+ @registers.has_key?(name.to_sym)
152
+ end
153
+
154
+ #
155
+ # Accesses a register.
156
+ #
157
+ # @param [String, Symbol] name
158
+ # The name of the register.
159
+ #
160
+ # @return [Register]
161
+ # The register.
162
+ #
163
+ # @raise [ArgumentError]
164
+ # The register could not be found.
165
+ #
166
+ def register(name)
167
+ name = name.to_sym
168
+
169
+ unless register?(name)
170
+ raise(ArgumentError,"unknown register: #{name}")
171
+ end
172
+
173
+ unless @allocated_registers.include?(name)
174
+ # mark the register as being used, when it was first accessed
175
+ @allocated_registers << name
176
+ end
177
+
178
+ return @registers[name]
179
+ end
180
+
181
+ #
182
+ # Adds a new instruction to the program.
183
+ #
184
+ # @param [String, Symbol] name
185
+ #
186
+ # @param [Array] operands
187
+ #
188
+ # @return [Instruction]
189
+ # The newly created instruction.
190
+ #
191
+ def instruction(name,*operands)
192
+ insn = Instruction.new(name.to_sym,operands)
193
+
194
+ @instructions << insn
195
+ return insn
196
+ end
197
+
198
+ #
199
+ # Creates an operand of size 1 (byte).
200
+ #
201
+ # @param [MemoryOperand, Integer] op
202
+ # The value of the operand.
203
+ #
204
+ # @return [MemoryOperand, ImmediateOperand]
205
+ # The new operand value.
206
+ #
207
+ def byte(op)
208
+ case op
209
+ when MemoryOperand
210
+ MemoryOperand.new(op.base,op.offset,op.index,op.scale,1)
211
+ else
212
+ ImmediateOperand.new(op,1)
213
+ end
214
+ end
215
+
216
+ #
217
+ # Creates a operand of size 2 (bytes).
218
+ #
219
+ # @param [MemoryOperand, Integer] op
220
+ # The value of the operand.
221
+ #
222
+ # @return [MemoryOperand, ImmediateOperand]
223
+ # The new operand value.
224
+ #
225
+ def word(op)
226
+ case op
227
+ when MemoryOperand
228
+ MemoryOperand.new(op.base,op.offset,op.index,op.scale,2)
229
+ else
230
+ ImmediateOperand.new(op,2)
231
+ end
232
+ end
233
+
234
+ #
235
+ # Creates a operand of size 4 (bytes).
236
+ #
237
+ # @param [MemoryOperand, Integer] op
238
+ # The value of the operand.
239
+ #
240
+ # @return [ImmediateOperand]
241
+ # The new operand value.
242
+ #
243
+ def dword(op)
244
+ case op
245
+ when MemoryOperand
246
+ MemoryOperand.new(op.base,op.offset,op.index,op.scale,4)
247
+ else
248
+ ImmediateOperand.new(op,4)
249
+ end
250
+ end
251
+
252
+ #
253
+ # Creates a operand of size 8 (bytes).
254
+ #
255
+ # @param [MemoryOperand, Integer] op
256
+ # The value of the operand.
257
+ #
258
+ # @return [MemoryOperand, ImmediateOperand]
259
+ # The new operand.
260
+ #
261
+ def qword(op)
262
+ case op
263
+ when MemoryOperand
264
+ MemoryOperand.new(op.base,op.offset,op.index,op.scale,8)
265
+ else
266
+ ImmediateOperand.new(op,8)
267
+ end
268
+ end
269
+
270
+ #
271
+ # Adds a label to the program.
272
+ #
273
+ # @param [Symbol, String] name
274
+ # The name of the label.
275
+ #
276
+ # @yield []
277
+ # The given block will be evaluated after the label has been
278
+ # added.
279
+ #
280
+ # @return [Symbol]
281
+ # The label name.
282
+ #
283
+ def label(name,&block)
284
+ name = name.to_sym
285
+
286
+ @instructions << name
287
+ instance_eval(&block)
288
+ return name
289
+ end
290
+
291
+ #
292
+ # Generic method for generating the instruction for causing an interrupt.
293
+ #
294
+ # @param [Integer] number
295
+ # The interrupt number to call.
296
+ #
297
+ # @abstract
298
+ #
299
+ def interrupt(number)
300
+ end
301
+
302
+ #
303
+ # Generic method for generating the instruction for invoking a syscall.
304
+ #
305
+ # @abstract
306
+ #
307
+ def syscall
308
+ end
309
+
310
+ #
311
+ # Generic method for pushing onto the stack.
312
+ #
313
+ # @param [Register, Integer] value
314
+ # The value to push.
315
+ #
316
+ # @abstract
317
+ #
318
+ def stack_push(value)
319
+ end
320
+
321
+ #
322
+ # Generic method for popping off the stack.
323
+ #
324
+ # @param [Symbol] name
325
+ # The name of the reigster.
326
+ #
327
+ # @abstract
328
+ #
329
+ def stack_pop(name)
330
+ end
331
+
332
+ #
333
+ # Generic method for clearing a register.
334
+ #
335
+ # @param [Symbol] name
336
+ # The name of the reigster.
337
+ #
338
+ # @abstract
339
+ #
340
+ def register_clear(name)
341
+ end
342
+
343
+ #
344
+ # Generic method for setting a register.
345
+ #
346
+ # @param [Symbol] name
347
+ # The name of the reigster.
348
+ #
349
+ # @param [Register, ImmediateOperand, Integer] value
350
+ # The new value for the register.
351
+ #
352
+ # @abstract
353
+ #
354
+ def register_set(name,value)
355
+ end
356
+
357
+ #
358
+ # Generic method for saving a register.
359
+ #
360
+ # @param [Symbol] name
361
+ # The name of the reigster.
362
+ #
363
+ # @abstract
364
+ #
365
+ def register_save(name)
366
+ end
367
+
368
+ #
369
+ # Generic method for loading a register.
370
+ #
371
+ # @param [Symbol] name
372
+ # The name of the reigster.
373
+ #
374
+ # @abstract
375
+ #
376
+ def register_load(name)
377
+ end
378
+
379
+ #
380
+ # Defines a critical region, where the specified Registers
381
+ # should be saved and then reloaded.
382
+ #
383
+ # @param [Array<Symbol>] regs
384
+ # The registers to save and reload.
385
+ #
386
+ # @yield []
387
+ # The given block will be evaluated after the registers
388
+ # have been saved.
389
+ #
390
+ def critical(*regs,&block)
391
+ regs.each { |name| register_save(name) }
392
+
393
+ instance_eval(&block)
394
+
395
+ regs.reverse_each { |name| register_load(name) }
396
+ end
397
+
398
+ #
399
+ # Evaluates code within the Program.
400
+ #
401
+ # @yield []
402
+ # The code to evaluate.
403
+ #
404
+ def eval(&block)
405
+ instance_eval(&block)
406
+ end
407
+
408
+ #
409
+ # Converts the program to Assembly Source Code.
410
+ #
411
+ # @param [Symbol] syntax
412
+ # The syntax to compile the program to.
413
+ #
414
+ def to_asm(syntax=:intel)
415
+ SYNTAX[syntax].emit_program(self)
416
+ end
417
+
418
+ #
419
+ # @see #to_s
420
+ #
421
+ def to_s
422
+ to_asm
423
+ end
424
+
425
+ #
426
+ # Assembles the program.
427
+ #
428
+ # @param [String] output
429
+ # The path for the assembled program.
430
+ #
431
+ # @param [Symbol, String] syntax
432
+ # The syntax to compile the program to.
433
+ #
434
+ # @param [Symbol] format
435
+ # The format of the assembled executable. May be one of:
436
+ #
437
+ # * `:dbg` - Trace of all info passed to object format module.
438
+ # * `:bin` - Flat format binary.
439
+ # * `:dosexe` - DOS .EXE format binary.
440
+ # * `:elf` - ELF.
441
+ # * `:elf32` - ELF (32-bit).
442
+ # * `:elf64` - ELF (64-bit).
443
+ # * `:coff` - COFF (DJGPP).
444
+ # * `:macho` - Mac OS X ABI Mach-O File Format.
445
+ # * `:macho32` - Mac OS X ABI Mach-O File Format (32-bit).
446
+ # * `:macho64` - Mac OS X ABI Mach-O File Format (64-bit).
447
+ # * `:rdf` - Relocatable Dynamic Object File Format (RDOFF) v2.0.
448
+ # * `:win32` - Win32.
449
+ # * `:win64` / `:x64` - Win64.
450
+ # * `:xdf` - Extended Dynamic Object.
451
+ #
452
+ # @return [String]
453
+ # The path to the assembled program.
454
+ #
455
+ # @raise [ArgumentError]
456
+ # The given syntax was not `:intel` or `:att`.
457
+ #
458
+ def assemble(output, syntax: :intel, format: :bin)
459
+ parser = PARSERS.fetch(syntax) do
460
+ raise(ArgumentError,"unknown ASM syntax: #{syntax.inspect}")
461
+ end
462
+
463
+ source = Tempfile.new(['ronin-code-asm', '.s'])
464
+ source.write(to_asm(syntax))
465
+ source.close
466
+
467
+ YASM::Command.run(
468
+ file: source.path,
469
+ parser: parser,
470
+ target: @arch,
471
+ output_format: format,
472
+ output: output
473
+ )
474
+
475
+ return output
476
+ end
477
+
478
+ protected
479
+
480
+ # undefine the syscall method, so method_missing handles it
481
+ undef syscall
482
+
483
+ #
484
+ # Allows adding unknown instructions to the program.
485
+ #
486
+ # @param [Symbol] name
487
+ # The name of the instruction.
488
+ #
489
+ # @param [Array] arguments
490
+ # Additional operands.
491
+ #
492
+ def method_missing(name,*arguments,&block)
493
+ if (block && arguments.empty?)
494
+ label(name,&block)
495
+ elsif block.nil?
496
+ if (arguments.empty? && register?(name))
497
+ register(name)
498
+ else
499
+ instruction(name,*arguments)
500
+ end
501
+ else
502
+ super(name,*arguments,&block)
503
+ end
504
+ end
505
+
506
+ end
507
+ end
508
+ end
509
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-code-asm - A Ruby DSL for crafting Assembly programs and shellcode.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-code-asm is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-code-asm is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-code-asm. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/code/asm/memory_operand'
22
+
23
+ module Ronin
24
+ module Code
25
+ module ASM
26
+ #
27
+ # Represents a Register.
28
+ #
29
+ class Register < Struct.new(:name, :width, :general)
30
+
31
+ #
32
+ # Initializes a register.
33
+ #
34
+ # @param [Symbol] name
35
+ # The register name.
36
+ #
37
+ # @param [Integer] width
38
+ # The width of the register.
39
+ #
40
+ # @param [Boolean] general
41
+ # Specifies whether the register is a General Purpose Register (GPR).
42
+ #
43
+ def initialize(name,width,general=false)
44
+ super(name,width,general)
45
+ end
46
+
47
+ #
48
+ # Adds an offset to the value within the register and dereferences the
49
+ # address.
50
+ #
51
+ # @param [MemoryOperand, Register, Integer] offset
52
+ # The offset to add to the value of the register.
53
+ #
54
+ # @return [MemoryOperand]
55
+ # The new Memory Operand.
56
+ #
57
+ # @raise [TypeError]
58
+ # the `offset` was not an {MemoryOperand}, {Register} or Integer.
59
+ #
60
+ def +(offset)
61
+ case offset
62
+ when MemoryOperand
63
+ MemoryOperand.new(self,offset.offset,offset.index,offset.scale)
64
+ when Register
65
+ MemoryOperand.new(self,0,offset)
66
+ when Integer
67
+ MemoryOperand.new(self,offset)
68
+ else
69
+ raise(TypeError,"offset was not an MemoryOperand, Register or Integer")
70
+ end
71
+ end
72
+
73
+ #
74
+ # Substracts from the value within the register and dereferences the
75
+ # address.
76
+ #
77
+ # @param [Integer] offset
78
+ # The value to subtract from the value of the register.
79
+ #
80
+ # @return [MemoryOperand]
81
+ # The new Memory Operand.
82
+ #
83
+ def -(offset)
84
+ MemoryOperand.new(self,-offset)
85
+ end
86
+
87
+ #
88
+ # Multiples the value within the register.
89
+ #
90
+ # @param [Integer] scale
91
+ # The scale to multiply the value within register by.
92
+ #
93
+ # @return [MemoryOperand]
94
+ # The new Memory Operand.
95
+ #
96
+ def *(scale)
97
+ MemoryOperand.new(nil,0,self,scale)
98
+ end
99
+
100
+ #
101
+ # @return [String]
102
+ # The register's name.
103
+ #
104
+ def to_s
105
+ self.name.to_s
106
+ end
107
+
108
+ end
109
+ end
110
+ end
111
+ end