ronin-code-asm 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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