Class: C64Asm::Block
- Inherits:
-
Array
- Object
- Array
- C64Asm::Block
- Defined in:
- lib/c64asm/asm.rb
Overview
Block is a raw machine code block Implements the non-magic of linking, aka symbol resolution.
Instance Attribute Summary collapse
-
#labels ⇒ Object
readonly
Returns the value of attribute labels.
-
#linked ⇒ Object
readonly
Returns the value of attribute linked.
Instance Method Summary collapse
-
#binary_pass ⇒ Object
Internal method, treat as private.
-
#dump ⇒ Object
Return verbose representation.
-
#dump_pass ⇒ Object
Internal method, treat as private.
-
#initialize ⇒ Block
constructor
Create new block.
-
#link(origin = 0x1000) ⇒ Object
Link resolves symbols and relative jumps given the origin.
-
#linker_pass(addr, pass) ⇒ Object
Internal method, treat as private.
-
#to_binary ⇒ Object
Turn block into byte string.
-
#to_s ⇒ Object
Return pretty string representation.
-
#to_source ⇒ Object
Return source code representation.
-
#write!(fname, mode = 'w', what = :prg) ⇒ Object
Write block to a given file in the given format This will probably overwrite the target file without warning.
Constructor Details
#initialize ⇒ Block
Create new block
441 442 443 444 445 |
# File 'lib/c64asm/asm.rb', line 441 def initialize @labels = {} @linked = false @chunks = {} end |
Instance Attribute Details
#labels ⇒ Object (readonly)
Returns the value of attribute labels.
438 439 440 |
# File 'lib/c64asm/asm.rb', line 438 def labels @labels end |
#linked ⇒ Object (readonly)
Returns the value of attribute linked.
438 439 440 |
# File 'lib/c64asm/asm.rb', line 438 def linked @linked end |
Instance Method Details
#binary_pass ⇒ Object
Internal method, treat as private
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
# File 'lib/c64asm/asm.rb', line 548 def binary_pass binary = '' each do |e| case e when Align binary += ([0] * (e.addr - @chunks[e.addr])).pack('C*') when Label true when Data binary += e.to_binary when Operand binary += e.to_binary when Block binary += e.binary_pass end end binary end |
#dump ⇒ Object
Return verbose representation
481 482 483 484 485 486 |
# File 'lib/c64asm/asm.rb', line 481 def dump link unless @linked lines = dump_pass lines.shift lines end |
#dump_pass ⇒ Object
Internal method, treat as private
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
# File 'lib/c64asm/asm.rb', line 506 def dump_pass addr = @linked.first lines = [] lines.push('$%0.4x ' % addr + " \t.block") each do |e| line = ('$%0.4x ' % addr).upcase block = false case e when Operand if e.mode == :r bytes = e.to_a.pack('Cc').unpack('C*') else bytes = e.to_a end line += bytes.to_a.collect{|e| '%0.2X' % e}.join(' ') line += ' ' * (9 - (3 * e.length)) line += " \t#{e.to_source}" addr += e.length when Align line += " \t#{e.to_source}" addr = e.addr when Label line += " #{e.to_source}" when Data line += ".. .. .. \t#{e.to_source}" addr += e.length when Block addr, lines_passed = e.dump_pass lines += lines_passed block = true end lines.push(line) unless block end lines.push('$%0.4x ' % addr + " \t.bend") [addr, lines] end |
#link(origin = 0x1000) ⇒ Object
Link resolves symbols and relative jumps given the origin
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
# File 'lib/c64asm/asm.rb', line 448 def link(origin = 0x1000) raise BlockError, 'Invalid origin' unless (origin >= 0 and origin <= 65535) # override origin if first non-Block element is an Align object felem = first while felem.class == Block felem = felem.first end if felem.instance_of? Align origin = felem.addr end endaddr = linker_pass(origin, :one) linker_pass(origin, :two) @linked end |
#linker_pass(addr, pass) ⇒ Object
Internal method, treat as private
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 |
# File 'lib/c64asm/asm.rb', line 569 def linker_pass(addr, pass) @labels = {} if pass == :one origin = addr each do |e| case e when Align raise BlockError, "Invalid alignment from $#{addr.to_s(16)} to $#{e.addr.to_s(16)}" if e.addr < addr @chunks[e.addr] = addr if pass == :one addr = e.addr when Label if pass == :one if @labels.has_key? e.name C64Asm.log :warn, "Redefinition of label #{e.name} from $#{@labels[e.name].to_s(16)} to $#{addr.to_s(16)}" end @labels[e.name] = addr end when Data addr += e.length when Operand if pass == :two unless e.ready? if e.label == :* arg = addr elsif @labels.has_key? e.label arg = @labels[e.label] else C64Asm.log :error, "Can't resolve label for #{e.to_s}" raise BlockError end if e.mode == :r arg = arg - addr -2 end e.resolve(arg) end end addr += e.length when Block addr = e.linker_pass(addr, pass) else C64Asm.log :error, "Invalid element #{e.to_s} in Block" raise BlockError end end @linked = [origin, addr] if pass == :one addr end |
#to_binary ⇒ Object
Turn block into byte string
475 476 477 478 |
# File 'lib/c64asm/asm.rb', line 475 def to_binary link unless @linked [@linked[0].ls_byte, @linked[0].ms_byte].pack('CC') + binary_pass end |
#to_s ⇒ Object
Return pretty string representation
472 |
# File 'lib/c64asm/asm.rb', line 472 def to_s; "<Block #{length}>"; end |
#to_source ⇒ Object
Return source code representation
467 468 469 |
# File 'lib/c64asm/asm.rb', line 467 def to_source (['.block'] + collect{|e| e.to_source} + ['.bend']).flatten end |
#write!(fname, mode = 'w', what = :prg) ⇒ Object
Write block to a given file in the given format This will probably overwrite the target file without warning.
490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/c64asm/asm.rb', line 490 def write!(fname, mode = 'w', what = :prg) File.open(fname, mode) do |fd| case what when :prg fd.write(to_binary) when :src fd.write(to_source.join("\n")) when :dump fd.write(dump.join("\n")) else raise BlockError, 'Unknown generation mode' end end end |