def assign_labels(section, labels, starting_address = 0):
    r'''Assign addresses to all labels in 'section'.

    Addresses are stored in 'labels' dict.  This is {label: address}.
    '''
    running_address = starting_address
    for block_id, block_label, block_address in assembler.gen_blocks(section):
        if block_address is None:
            address = running_address
            assembler.update_block_address(block_id, address)
        else:
            address = block_address
        assert block_label not in labels, \
               "duplicate assembler label: " + block_label
        labels[block_label] = address
        for label, opcode, op1, op2 in assembler.gen_insts(block_id):
            if label is not None:
                assert label not in labels, \
                       "duplicate assembler label: " + label
                labels[label] = address
            if opcode is not None:
                address += getattr(asm_opcodes, opcode.upper()) \
                             .length(op1, op2)[1]
        if address > running_address:
            running_address = address
    return running_address
def assemble_word(block_id, block_address, labels):
    r'''Yields the individual bytes for all instructions in an assembler block.

    The bytes are generated taking byte swapping into account.  The AVR is
    little-endian, so the least significant byte of each instruction word is
    generated first.
    '''
    address = block_address
    for label, opcode, op1, op2 in assembler.gen_insts(block_id):
        if opcode is not None:
            inst = getattr(asm_opcodes, opcode.upper())
            for n in inst.assemble(op1, op2, labels, address):
                yield n
                address += 1