Чем отличаются команды ret и reti
Перейти к содержимому

Чем отличаются команды ret и reti

  • автор:

Система команд микроконтроллеров AVR

Микроконтроллеры (далее — МК) серии AVR имеют от 90 до 120 команд в зависимости от модели. Здесь рассмотрены только те команды, которые использованы в нашей программе.

ADD

Синтаксис: ADD reg1, reg2

Эта команда складывает содержимое регистров reg1 и reg2, сохраняя результат в регистре reg1. Изменяет состояние флагов H, S, V, N, Z, C.

AND

Синтаксис: AND reg1, reg2

Эта команда выполняет операцию «Логическое И» между регистрами reg1 и reg2, сохраняя результат в регистре reg1. Изменяет состояние флагов S, V, N, Z.

ANDI

Синтаксис: ANDI hreg, number

Эта команда выполняет операцию «Логическое И» между содержимым старшего регистра hreg и константой number (0…255), сохраняя результат в регистре. Изменяет состояние флагов S, V, N, Z.

BRBC

Синтаксис: BRBC bit, label

Эта команда проверяет состояние бита регистра SREG ($3F) и переходит к метке label, если бит сброшен. Метка должна находиться в пределах 63 команд от команды brbc.

BRBS

Синтаксис: BRBS bit, label

Эта команда проверяет состояние бита регистра SREG ($3F) и переходит к метке label, если бит установлен. Метка должна находиться в пределах 63 команд от команды brbs.

BRCC

Синтаксис: BRCC bit, label

Эта команда проверяет флаг переноса (С) и переходит к метке label, если он сброшен.

BRCS

Синтаксис: BRCS bit, label

Эта команда проверяет флаг переноса (С) и переходит к метке label, если он установлен.

BREQ

Синтаксис: BREQ bit, label

Эта команда проверяет флаг нуля (Z) и переходит к метке label, если он установлен.

BRNE

Синтаксис: BRNE bit, label

Эта команда проверяет флаг нуля (Z) и переходит к метке label, если он сброшен.

CBI

Синтаксис: CBI ioreg, bit

Эта команда сбрасывает в 0 бит регистра ввода-вывода ioreg ($00…$1F). Номер бита определяет операнд bit.

CLR

Синтаксис: CLR reg

Эта команда сбрасывает все биты регистра reg в 0. Изменяет состояние флагов S, V, N, Z.

CP

Синтаксис: CP reg1, reg2

Эта команда сравнивает содержимое регистров reg1 и reg2 путем вычитания reg2 из reg1. Содержимое регистров не изменяется. Изменяет состояние флагов H, S, V, N, Z, C.

CPI

Синтаксис: CPI hreg, number

Эта команда сравнивает содержимое регистра hreg с константой number путем вычитания константы из регистра. Содержимое регистров не изменяется. Изменяет состояние флагов H, S, V, N, Z, C. Команда работает только с регистрами R16…R31.

DEC

Синтаксис: DEC reg

Эта команда уменьшает на единицу содержимое регистра reg, записывая результат обратно в регистр. Изменяет состояние флагов S, V, N, Z.

IN

Синтаксис: IN reg, ioreg

Эта команда пересылает содержимое регистра ввода-вывода ioreg в РОН reg.

INC

Синтаксис: INC reg

Эта команда увеличивает на единицу содержимое регистра reg, записывая результат обратно в регистр. Изменяет состояние флагов S, V, N, Z.

LD

Синтаксис: LD reg, longreg

Эта команда загружает один байт из памяти данных (адрес ячейки памяти содержится в регистре longer) в регистр reg (для модели 1200).

LDI

Синтаксис: LDI hreg, number

Эта команда загружает непосредственное значение number в старший регистр hreg (команда может работать только с регистрами R16…R31). Число number должно находиться в пределах 0…255.

LSR

Синтаксис: LSR reg

Эта команда выполняет логический сдвиг вправо содержимого регистра reg. При этом 0-й бит копируется в флаг C, 7-й бит сбрасывается в 0. Изменяет состояние флагов S, V, N, Z, C.

ORI

Синтаксис: ORI hreg, number

Эта команда выполняет операцию «Логическое ИЛИ» между содержимым старшего регистра hreg и константой number (0…255), сохраняя результат в регистре. Изменяет состояние флагов S, V, N, Z.

OUT

Синтаксис: OUT ioreg, reg

Эта команда пересылает содержимое регистра общего назначения reg в регистр ввода-вывода ioreg.

RCALL

Синтаксис: RCALL label

Эта команда вызывает подпрограмму, обозначенную меткой label, которая должна находиться в пределах 2048 команд от команды rcall (относительный вызов).

RET

Синтаксис: RET

Эта команда выполняет возврат из подпрограммы, переходя на команду, которая следует за исходной командой call.

RETI

Синтаксис: RETI

Эта команда выполняет возврат из подпрограммы и устанавливает флаг общего разрешения прерываний.

RJMP

Синтаксис: RJMP label

Относительный переход. Выполняет переход к участку программы, обозначенному меткой label, которая должна находиться в пределах 2048 от команды RJMP.

SBI

Синтаксис: SBI ioreg, bit

Эта команда устанавливает в 1 бит регистра ввода-вывода ioreg ($00…$1F). Номер бита определяет операнд bit.

SBIC

Синтаксис: SBIC ioreg, bit

Эта команда проверяет бит регистра ввода-вывода ioreg ($00…$1F) и пропускает следующую команду, если этот бит сброшен. Номер бита определяет операнд bit.

SBIS

Синтаксис: SBIS ioreg, bit

Эта команда проверяет бит регистра ввода-вывода ioreg ($00…$1F) и пропускает следующую команду, если этот бит установлен. Номер бита определяет операнд bit.

SEI

Синтаксис: SEI

Эта команда устанавливает флаг общего разрешения прерываний.

SER

Синтаксис: SER reg

Эта команда устанавливает все биты регистра reg в 1. Изменяет состояние флагов S, V, N, Z. Команда может работать только с регистрами R16…R31.

ST

Синтаксис: ST reg, longreg

Для модели 1200 эта команда сохраняет содержимое регистра reg в памяти данных (адрес ячейки памяти содержится в регистре longer), т.е. косвенно пересылает содержимое РОН reg по адресу, хранящемуся в регистре longer.

SUBI

Синтаксис: SUBI hreg, number

Вычитает из старшего регистра hreg константу number. Результат сохраняется в этом же регистре. Изменяет состояние флагов H, S, V, N, Z, C. Команда может работать только с регистрами R16…R31.

Команды передачи управления

Все команды группы передачи управления приведены в табл.3. Микроконтроллеры AVR могут содержать до 4-х разновидностей команды безусловного перехода. Команды такого типа модифицируют
содержимое программного счётчика, после чего программа продолжает выполняться с нового места (адреса перехода). Безусловный переход в памяти программ происходит не зависимо от каких либо условий, флагов программы и т.д. Инструкция rjmp k (Относительный безусловный переход) позволяет осуществить переход в диапазоне +2047…-2047 слов в памяти программ от места где она расположена. Адрес перехода при этом зависит от текущего значения программного счётчика и вычисляется как смещение PC+1+k. Команда ijmp (Косвенный безусловный переход) производит переход в памяти программ в пределах 0…65535 слов по адресу, находящемуся в индексном регистре Z. В этом случае адрес перехода является переменной величиной доступной из программы. Это даёт возможность легко реализовать процедуру ветвления, когда в зависимости от условий должен быть выполнен тот или иной фрагмент кода. В моделях с объёмом памяти программ 256 кб доступна также команда eijmp (Расширенный безусловный косвенный переход). Она использует 3-байтовый указатель адреса EIND:ZH:ZL. В регистре EIND из пространства РВВ находится 17-тый бит адреса, а переход осуществляется в пределах 0…131071 слов. Команда jmp k (Абсолютный безусловный переход) — переход по адресу k в любую точку из любого места программы. Абсолютный адрес перехода находится в коде операции, а команда занимает 2 слова (4 байта) и выполняется в течении 3-х машинных циклов. При использовании команд передачи управления в качестве параметров обычно используют метки, в место которых после компоновки программы будут подставлены реальные адреса (смещения относительно адреса):

ldi ZL,low(label) ;косвенный переход на метку label ldi ZH,high(label) ijmp . jmp label ;абсолютный переход на метку label . rjmp label ;относительный переход на метку label . .org 0x0200 label:. ;метка в программе по адресу 0x0200

Другим типом команд являются вызовы подпрограмм. Существуют следующие их разновидности: rcall k (Относительный вызов подпрограммы), icall (Косвенный вызов подпрограммы), eicall (Расширенный косвенный вызов подпрограммы) и call k (Абсолютный вызов подпрограммы). Функционируют такие инструкции аналогично командам безусловного перехода, но с одним существенным отличием. Перед переходом в памяти программ, адрес следующей команды предварительно сохраняется в специально отведённой для этих целей области памяти (стеке). Таким образом, находясь в любой точке программы, сохраняется возможность вернутся в то место, из которого был осуществлен вызов. Это действие осуществляет команда ret (Возврат из подпрограммы). Она загружает в PC сохранённый в стеке адрес возврата, после чего программа продолжает выполняться со следующей команды после rcall k, icall, eicall, call k:

ldi ZL,low(func1);косвенный вызов подпрограммы func1 ldi ZH,high(func1) icall . call func1 ;абсолютный вызов подпрограммы func1 . rcall func1 ;относительный вызов подпрограммы func1 . func1:. ;подпрограмма func1 call func2 ;абсолютный вызов подпрограммы func2 . ret ;возврат из подпрограммы func1 func2:. ;подпрограмма func2 ret ;возврат из подпрограммы func2

В приведенном примере подпрограмма func1 может вызываться много раз из различных мест программы. Кроме того, в теле самой подпрограммы func1 могут содержаться вызовы различных подпрограмм (вызов func2 и т.д.). Такая организация программы позволяет максимально эффективно использовать ресурсы процессора, делает код более наглядным и позволяет многократно использовать разработанные подпрограммы в дальнейших проектах. Еще одним скрытым механизмом вызова подпрограмм являются аппаратные прерывания. При их возникновении происходит вызов подпрограммы (обработчика прерывания) по фиксированному адресу (вектору прерывания), при этом адрес возврата также запоминается в стеке. Но в отличии от вызова по командам rcall k, icall, eicall, call k ещё и автоматически сбрасывается флаг глобального разрешения прерываний I в регистре SREG, т.е. запрещаются прерывания во время прерывания. Для выхода из прерывания используется команда reti (Возврат из прерывания) которая, загружает в PC адрес возврата и восстанавливает флаг I (разрешает прерывания при выходе из прерывания):

.org 0x0002 rjmp service_INT0 ;вектор внешнего прерывания INT0 .org 0x0100 service_ INT0: ̣̣̣̣̣̣̣̣ ;обработчик прерывания INT0 reti ;возврат в основную программу

Иногда командой reti удобно завершить и обычную подпрограмму. Так бывает, когда, например, при выходе необходимо разрешить прерывания. В этом случае она фактически заменяет собой две инструкции sei (Разрешение прерываний) и ret:

func: cli ;глобальный запрет прерываний (I=0) . reti ;выход из подпрограммы и разрешение прерываний

Время выполнения rcall k, icall, call k, ret, reti зависит от величины программного счётчика конкретной модели. Если его разрядность более 16 бит (≥ 128 кб FLASH памяти), то для сохранения 3-байтового адреса возврата требуется на один машинный цикл больше. В данную группу команд включены также 4 инструкции сравнения: cp Rd,Rr (Сравнить регистры), cpс Rd,Rr (Сравнить регистры с учётом переноса), cpi Rd,K (Сравнить регистр c константой), cpse Rd,Rr (Сравнить регистры и пропустить команду если они равны). Строго говоря первые три из них не являются командами передачи управления, так как не могут оказать влияние на счётчик программ. Единственным их предназначением является сравнение числовых величин, находящихся в РОН. Как видно из описания, команда cp Rd,Rr аналогична sub Rd,Rr, вместо cpc Rd,Rr фактически выполняется sbc Rd,Rr, а вместо cpi Rd,K — cubi Rd,K. Разница заключается только лишь в том, что содержимое регистра Rd остаётся неизменным. При этом переопределяется значение флагов Z,C,S, N,V,H регистра SREG по которым и можно судить о соотношении между числовыми величинами. В частности, сравнение двухбайтовых чисел находящихся в регистровых парах R19:R18 R17:R16 можно выполнить следующим образом:

cp R18, R16 ; сравнение 2-байтовых чисел cpc R19, R17 ; R19:R18 - R17:R16

В этом примере флага C окажется установленным, когда R19:R18< R17:R16 (сброшенным, когда R19:R18>R17:R16). Что касается флага Z, то в данном случае он не может быть критерием проверки на нуль (Z=1 будет свидетельствовать только о равенстве R19=R17+C). Стоит заметить также, что, подобно всем остальным командам, использующим непосредственную адресацию, cpi Rd,K может работать только с регистрами R16…R31. Инструкция cpse Rd,Rr выполняется иначе. Она относится к типу Test and Skip (Проверка и пропуск). По логике работы команды такого рода выполняют проверку определённого условия и если оно истинно (в данном случае если Rd=Rr), то следующая в тексте команда пропускается. При этом все флаги программы остаются неизменными. Помимо этого существуют ещё 4 команды Test and Skip ориентированных на проверку состояния определённого бита в регистрах. Две из них работают с РОН: sbrc Rr,b (Пропуск команды, если бит регистра сброшен), sbrs Rr,b (Пропуск команды, если бит регистра установлен). Ещё две с РВВ: sbic P,b (Пропуск команды, если бит регистра ввода-вывода сброшен), sbis P,b (Пропуск команды, если бит регистра ввода-вывода установлен). Если бит b(0…7) установлен при выполнении команд sbrs Rr,b и sbis P,b или сброшен для sbrc Rr,b, sbic P,b, то производится пропуск следующей команды. Нижеприведённый код демонстрирует программную задержку до тех пор пока не будет нажата кнопка подключённая к линии 1 порта B (пока бит 1 РВВ PINB не будет сброшен):

button_press: sbic PINB,1 ; задержка пока на выводе 1 порта B rjmp button_press ; не появится низкий уровень .

В отличии от команд sbrs Rr,b, sbrc Rr,b, которые работают со всеми без исключения РОН, инструкции sbis P,b, sbic P,b могут использовать только первые 32 РВВ. Если учесть, что число управляющих РВВ на много больше то, это довольно существенное ограничение. Конечно те РВВ, доступ к битам которых наиболее важен, разработчики постарались разместить именно в этой области. К ним относятся все регистры управления портами A,B,C,D,E,F, а также ряд других, отвечающих за работу EEPROM, USART, SPI т.д. Во всех остальных случаях необходимо cкопировать содержимое РВВ в один из РОН и уже дальше анализировать состояние соответствующего бита. Программное ожидание сброса бита 2 порта J должно выглядеть следующим образом:

button_press: lds R16,PINJ ; задержка пока на выводе 2 порта J sbrc R16,2 ; не появится низкий уровень rjmp button_press .

Время выполнения инструкций Test and Skip может быть различным в зависимости от того пропускается следующая команда или нет. В первом случае необходимо 2 машинных цикла, во втором 1. Если же производится пропуск “длинной” команды состоящей из двух слов (lds Rd,k, jmp k и т.д.) на выполнение операции уйдёт 3 цикла. Флаги программы регистра состояния также не доступны инструкциям sbis P,b, sbic P,b, но из-за важности их значения предусмотрены две команды условного перехода разработанных специально для работы с SREG: brbs s,k (Переход, если бит регистра SREG установлен), brbc s,k (Переход, если бит регистра SREG сброшен). Когда соответствующий бит s в SREG установлен для brbs s,k или сброшен для brbс s,k производится относительный переход в пределах +63…-63 слов (PC+k+1). Ассемблер AVR поддерживает по 9 различных форм написания инструкций brbs s,k, brbc s,k для разных значений флагов программы (табл.4). Табл 4. Команды условных переходов по состоянию флагов SREG:

Проверка
флага
Команда условного
перехода
Альтернативная
Форма написания
Условие перехода
C brbc 0,k brcc k Переход если флаг переноса установлен
brsh k Переход если больше или равно
brbs 0,k brcs k Переход если флаг переноса сброшен
brlo k Переход если меньше
Z brbc 1,k breq k Переход если равно
brbs 1,k brne k Переход если не равно
N brbc 2,k brpl k Переход если плюс
brbs 2,k brmi k Переход если минус
V brbc 3,k brvc k Переход если флаг дополнительного кода сброшен
brbs 3,k brvs k Переход если флаг дополнительного кода установлен
S brbc 4,k brge k Переход если больше или равно нулю (знаковое)
brbs 4,k brlt k Переход если меньше нуля (знаковое)
H brbc 5,k brhc k Переход если флаг половинного переноса сброшен
brbs 5,k brhs k Переход если флаг половинного переноса установлен
T brbc 6,k brtc k Переход если флаг хранения бита сброшен
brbs 6,k brts k Переход если флаг хранения бита установлен
I brbc 7,k brid k Переход если прерывания запрещены
brbs 7,k brie k Переход если прерывания разрешены

В ходе программы, как правило, наиболее часто производится проверка флагов Z и C. Если установка флага Z однозначно свидетельствует о нулевом результате операции, то установка флага переноса C может иметь разный смысл в зависимости от того, какая команда оказывает на него влияние. Следующая подпрограмма осуществляет инкрементирование 4-байтового счётчика R27:R26:R25:R24, а проверка флага C производится с целью установить, происходит ли переполнение младшего слова R25:R24, и если да, то к старшей регистровой паре R27:R26 добавляется 1:

inc_cnt: adiw R24,1 ; добавление 1 к регистровой паре R25:R24 brcc PC+2 ; и если возникает перенос, то adiw R26,1 ; увеличение на 1 регистровой пары R27:R26 ret

Другим примером, где необходимо знать состояние флага C, может служить сравнение чисел:

cpi R16,0x40 ; сравнить содержимое R16 с числом 0x40 brlo ulo ; перейти наметку ulo если R16 < 0x40 . ulo: .

Вместо brcc k, здесь используется более подходящая по смыслу форма написания инструкции brlo k (переход если R16 меньше 0x40). Подобный понятный символический вид имеют и остальные команды условных относительных переходов: breq k(Переход если равно 0), brne k(Переход если не равно 0), brie k (Переход если прерывания разрешены), brid k (Переход если прерывания запрещены) и т.д. Перейти к следующей части: Группа команд операций с битами

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0

Вознаградить Я собрал 0 0

Оценить статью

  • Техническая грамотность

Прерывания

Это аппаратные события. Ведь у микроконтроллера кроме ядра есть еще дофига периферии. И она работает параллельно с контроллером. Пока контроллер занимается вычислением или гоняет байтики по памяти — АЦП может яростно оцифровывать входное напряжение, USART меланхолично передавать или принимайть байтик, а EEPROMка неспеша записывать в свои тормозные ячейки очередной байт.

А когда периферийное устройство завершает свою работу оно поднимает флаг готовности. Мол, чувак, у меня все пучком, забирай результат. Процессор может проверить этот флаг в общем цикле и как то его обработать.

Но некоторые события в принципе не могут ждать, например USART - вовремя не обработаешь входящий байт, считай провафлил передачу, т.к. передающий девайс пошлет второй, ему плевать успел ты его обработать или нет. Для таких срочных дел есть прерывания.

У AVR этих прерываний с полтора десятка наберется, на каждое переферийное устройство по прерыванию, а на некотрые и не по одному. Например, у USART их целых три - Байт пришел, Байт ушел, Передача завершена.

Как это работает

Когда случается прерывание, то процессор тут же завершает текущую команду, пихает следующий адрес в стек (точно также как и при CALL) и переходит… А куда, собственно, он переходит?

А переходит он на фиксированный вектор прерывания. За каждым аппаратным прерыванием закреплен свой именной адрес. Все вместе они образуют таблицу векторов прерывания. Расположена она в самом начале памяти программ. Для Атмега16, используемой в Pinboard таблица прерываний выглядит так:

RESET 0x0000 ; Reset Vector

INT0addr 0x0002 ; External Interrupt Request 0

INT1addr 0x0004 ; External Interrupt Request 1

OC2addr 0x0006 ; Timer/Counter2 Compare Match

OVF2addr 0x0008 ; Timer/Counter2 Overflow

ICP1addr 0x000a ; Timer/Counter1 Capture Event

OC1Aaddr 0x000c ; Timer/Counter1 Compare Match A

OC1Baddr 0x000e ; Timer/Counter1 Compare Match B

OVF1addr 0x0010 ; Timer/Counter1 Overflow

OVF0addr 0x0012 ; Timer/Counter0 Overflow

SPIaddr 0x0014 ; Serial Transfer Complete

URXCaddr 0x0016 ; USART, Rx Complete

UDREaddr 0x0018 ; USART Data Register Empty

UTXCaddr 0x001a ; USART, Tx Complete

ADCCaddr 0x001c ; ADC Conversion Complete

ERDYaddr 0x001e ; EEPROM Ready

ACIaddr 0x0020 ; Analog Comparator

TWIaddr 0x0022 ; 2-wire Serial Interface

INT2addr 0x0024 ; External Interrupt Request 2

OC0addr 0x0026 ; Timer/Counter0 Compare Match

SPMRaddr 0x0028 ; Store Program Memory Ready

Как видишь, это первые адреса флеша. На каждый вектор отводится по два байта в которые мы можем записать любую команду. Но что попало туда обычно не вписывают, а ставят сразу JMP на какую нибудь метку, где уже можно спокойно сделать все что душе угодно, не стесняясь размеров кода.

Запишем эту бодягу в цивильной форме, через ORG и добавим немного кода.

.ORG $000 ; (RESET)

RJMP Reset

RETI ; (INT0) External Interrupt Request 0

RETI ; (INT1) External Interrupt Request 1

RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match

RETI ; (TIMER2 OVF) Timer/Counter2 Overflow

RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event

RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A

RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B

RETI ; (TIMER1 OVF) Timer/Counter1 Overflow

RETI ; (TIMER0 OVF) Timer/Counter0 Overflow

RETI ; (SPI,STC) Serial Transfer Complete

RJMP RX_OK ; (USART,RXC) USART, Rx Complete

RETI ; (USART,UDRE) USART Data Register Empty

RETI ; (USART,TXC) USART, Tx Complete

RETI ; (ADC) ADC Conversion Complete

RETI ; (EE_RDY) EEPROM Ready

RETI ; (ANA_COMP) Analog Comparator

RETI ; (TWI) 2-wire Serial Interface

RETI ; (INT2) External Interrupt Request 2

RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match

RETI ; (SPM_RDY) Store Program Memory Ready

.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний

; Это обработчик прерывания. Тут, на просторе, можно наворотить сколько

; угодно кода.

RX_OK: IN R16,UDR ; Тут мы делаем что то нужное и полезное

RETI ; Прерывание завершается командой RETI

Reset: LDI R16,Low(RAMEND) ; Инициализация стека

OUT SPL,R16 ; Обязательно.

LDI R16,High(RAMEND)

OUT SPH,R16

SEI ; Разрешаем прерывания глобально

OUT UCSRB,R17

Теперь разберем эту портянку. Контроллер стартует с адреса 0000, это точка входа. Там мы сразу же делаем бросок на метку RESET. Если это не сделать, то контроллер пойдет выполнять команды из таблицы векторов, а они не для того там посажены. Да и не далеко он ускачет — без инициализации стека и наличия адреса возврата в нем первый же RETI вызовет коллапс. Ведь RETI работает почти также как и RET.

Поэтому сразу уносим оттуда ноги на RESET. Где первым делом инициализируем стек. А потом, командой SEI, разрешаем прерывания. И установкой бита в регистре периферии UCSRB включаем прерывание по приему байта.

Дальше зацикливаемся и ждем когда в приемный буффер USART извне свалится байт. Запускай это дело в эмуляцию и начинай трассировать по одной команде. Сначала, как я и говорил, проц прыгнет на метку Reset, потом выставит нужные значения и наглухо зациклится на

До прихода байта. Но как же нам осуществить этот приход байта если весь наш эксперимент не более чем симуляция виртуального процессора в отладчике? А очень просто!

Вручную вписать этот байт в регистр и вручную же протыкать флаг, словно байт пришел. За прием байта отвечает флаг RXC в регистре периферии UCSRA, раздел USART. Найди там бит RXC и тыкни его, чтобы закрасился. Все, прерывание вроде как наступило.

Нажми F11, чтобы сделать еще один шаг по программе… Опа, стрелочка улетела в таблицу векторов, как раз на вектор

RJMP RX_OK ; (USART,RXC) USART, Rx Complete

А оттуда уже прыжок сразу же на метку RX_OK, где мы забираем данные из регистра UDR в R17 и выходим из прерывания, по команде RETI.

При этом процессор вернется в наш бесконечный цикл, в то место откуда прерывался.

Вот, как это было, если по коду:

Вот, вроде теперь вопросов по выполнению быть не должно.

Разрешение и запрещение прерываний Прерываний много, но по умолчанию они все запрещены. Во-первых, глобально — есть в процессоре в регистре SREG (о нем чуть позже) флаг I (interrupt) когда он равен 0, то все прерывания запрещены вообще, глобально, все без исключения.

Когда он равен 1, то прерывания глобально разрешены, но могут быть запрещены локально.

Устанавливается и сбрасывается этот флаг командами

  • SEI - разрешить прерывания
  • CLI - запретить прерывания (Да, по поводу моего ника, DI это, кстати, то же самое что и CLI, но для процессора Z80 ;) )
1 IN R16,UDR

Либо флаг скидывают вручную - записью в этот флаг единицы. Не нуля! Единицы! Подробней в даташите на конкретную периферию. Очередность прерываний Но что будет если произошло одно прерывание и процессор ушел на обработчик, а в этот момент произошло другое прерывание? А ничего не будет, при уходе на прерывание происходит аппаратный глобальный запрет всех других прерываний– просто сбрасывается флаг I, а по команде RETI, при возврате, этот флаг устанавливается в 1. В этом, кстати, отличие RET от RETI Но! Никто не запрещает нам внутри обработчика поставить SEI и разрешить прерывания. При этом мы получим вложенные прерывания. Можно, но это опасно. Черевато переполнением стека и прочими гадостями. Так что это надо делать с твердым осознанием последствий. Что тогда? Прерывание которое пришло во время обработки первого потеряется? Нет, не потеряется. Флаг то его события никто сам не снимет, так что только процессор выйдет из первого обработчика (разреша при этом глобальные прерывания), как это не снятый флаг сгенерирует новое прерывание и процессор его обработает. А теперь такая ситуация — прерывания запрещены, неважно по какой причине, и тут приходит два прерывания. Поднимает каждая свой флажок и оба ждут глобального разрешения. SEI. Кто пойдет первым? А первым пойдет то прерывание, чей вектор меньше по адресу, ближе к началу памяти. За ним второй. В случае когда пришло несколько прерываний одного типа. Скажем, пока мы там ковырялись в обработчике, нам сбоку тут еще таймер три раза тикнул своим флагом, то обработается только одно событие, остальные могут потеряться. Бег по граблям Прерывания штука мощная, но опасная. С их помощью плодятся такие глюки, по сравнению с которыми стековые срывы так — семечки. Вся засада багов из-за кривых прерываниях в том, что их практически невозможно отследить в отладчике. Возникает плавающий глюк, появление которого зависит от того в каком именно месте кода произойдет вызов прерывания. Что поймать, сам понимаешь, почти невозможно. Так что если у МК то понос, то золотуха, то программа петухом поет, а то молчит как рыба — знай, в 95% копать собаку надо в районе прерываний и их обработчиков. Но если правильно написать прерывание, то багов оно не даст. Главное понимать в чем его опасность. Грабли первые — спасай регистры. Прерывание, когда оно разрешено, вызывается ВНЕЗАПНО, между двумя произвольными инструкциями кода. Поэтому очень важно, чтобы к моменту когда мы из прерывания вернемся все осталось как было. Все регистры, используемые в обработчике прерываний, должны быть предварительно сохранены. Также должен быть сохранен регистр флагов SREG, в котором хранится результат логических операций. Результаты проще всего сохранять в стеке. Приведу пример: Вот есть у нас обработчик прерывания который сравнивает байт на входе в USART и если он равен 10, выдает обратно отклик ‘t’ (ten в смысле).

1 2 3 4 5 6 7 8 9 10 11 RX_OK: IN R16,UDR CPI R16,10 BREQ Ten RJMP Exit Ten: LDI R17,'t' OUT UDR,R17 Exit:

И у нас есть код. Код скопипащен от балды из какого то проекта, даже пояснять не буду, не в нем суть.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 . . . LPM R18,Z CPI R18,0 BREQ ExitStr SUBI R16,65 LSL R16 LDI ZL,Low(Ltrs*2) LDI ZH,High(Ltrs*2) ADD ZL,R16 ADC ZH,R1 . . .

Согласно идеи прерывания, наш обработчик может воткнуться между двумя любыми инструкциями. Например, так:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 . . . LPM R18,Z CPI R18,0 BREQ ExitStr SUBI R16,65 >>>>>>>>>>>Прерывание >>>>>>>>>>> RX_OK: IN R16,UDR CPI R16,10 BREQ Ten RJMP Exit Ten: LDI R17,'t' OUT UDR,R17 Exit: RETI LSL R16 LDI ZL,Low(Ltrs*2) LDI ZH,High(Ltrs*2) ADD ZL,R16 ADC ZH,R1 . . .

До входа в прерывание, после команды SUBI R16,65 в R16 было какое то число из которого вычли 65. И дальше с ним должны были провернуть операцию логического сдвига LSL R16, но тут вклинился обработчик, где в R16 записалось значение из UDR. И мы выпали из обработчика перед командой LSL R16, но в R16 уже мусор какой то. Совершенно не те данные, что мы планировали. Естественно вся логика работы от такого издевательства порушилась и возник глюк. Но стоит прерыванию прийти чуть раньше, на одну микросекунду — как глюк исчезнет, т.к. SUBI R16,65 будет уже после прерывания и логика не будет порушена, но может возникнуть другой глюк. Полная лотерея, повезет не повезет. Может вылезти сразу, а может и через год идеальной работы, а потом также сгинет и сиди чеши репу что же это было - сбой по питанию, бага, или таракан по плате пробежал неудачно. Чтобы такого не было в обязательно порядке надо сохранять регистры и SREG на входе в прерывание и доставать на выходе. У нас тут, в обработчике, используется R17 и R16 и SREG (в него помещается результат работы команды CPI). Вот их и сохраним. Выглдеть это будет так:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 RX_OK: PUSH R16 ; Сохранили R16 IN R16,SREG ; Достали SREG в R16 PUSH R16 ; Утопили его в стеке PUSH R17 ; Туда же утопили R17 ; Теперь можно со спокойной совестью работу работать. IN R16,UDR CPI R16,10 BREQ Ten RJMP Exit Ten: LDI R17,'t' OUT UDR,R17 ; А на выходе вернем все как было. ; Достаем в обратном порядке Exit: POP R17 POP R16 OUT SREG R16 POP R16 RETI ; Спокойно выходим. Регистры вернул как было.

Как же выносить данные из прерываний? Да по разному, можно в память сохранять, можно для этого спец регистр заиметь и знать, что он может в любой момент измениться в прерывании. Грабли вторые — не тормози. Прерывания отвлекают процессор от основных дел, более того, они блокируют другие прерывания. Поэтому в прерывании главное все сделать максимально быстро и свалить. Никаких циклов задержки, никаких долгоиграющих процедур. Никаких ожиданий аппаратного события. СКОРОСТЬ! СКОРОСТЬ! СКОРОСТЬ! Вот что должно тобой руководить при написании обработчика. Заскочил — сделал — выскочил! Но такая красивая схема возможна далеко не всегда. Иногда бывает надо по прерыванию делать и медленные вещи. Например, прием байтов из интерфейса и запись их в какую нибудь медленную память, вроде EEPROM. Как тогда быть? А тут делают проще. Цель прерывания — во что бы то ни стало среагировать на событие именно в тот момент, когда оно пришло, чтобы не прозевать. А вот обрабатывать его прямо сейчас обычно и не обязательно. Заскочил в обработчик, схватил быстро тухнущие данные, перекинул их в буффер где им ничего не угрожает, поставил где-нибудь флажок отметку “мол там байт обработать надо” и вышел. Все! Остальное пусть сделает фоновая программа в порядке общей очереди. Либо, если иначе никак нельзя, разрешай прерывания внутри обработчика, но смотри чтобы не возникли рекурсивные прерывания, когда один и тот же обработчик разрешает прерывания сам себе, образуя множественные вложенные вызовы с зарыванием в стек. Грабли третьи — атомарный доступ Есть ряд операций которые должны выполняться неразрывно. Например, чтение 16ти разрядных регистров таймера. Ядро то у нас восьми-разрядное, поэтому 16ти разрядный регистр таймера считывается в два приема сначала младший байт, а потом старший. И вот в этом месте нельзя ни в коем случае допускать, чтобы между считыванием младшего и старшего было прерывание. Т.к. после выхода из прерывания таймер уже может много чего натикать и информация уже будет не актуальная. Поэтому перед чтением делаем CLI, а после SEI. Также нельзя разрешать прерывания если одна и та же многоходовая операция делается и в прерывании и в главном цикле. Например, прерывание хватает байты из АЦП и пишет их в буффер (ОЗУ), образуя связные цепочки данных. Главный же цикл периодически из этого буффера данные читает. Так вот, на момент чтения буффера из памяти, надо запрещать прерывания, чтобы никто не посмел в этот буффер что-нибудь записать. Иначе мы можем получить невалидные данные — половина байтов из старого замера, половина из нового. Причем, во многих случаях не обязательно глобально блокировать все прерывания вообще, достаточно заблокировать то локальное прерывание, которое может нам нагадить. Грабли четвертые — не блокируй. Третие грабли нужно внимательно обходить, но в паранойю впадать тоже не следует. Тупо запрещать прерывания везде, где мерещится бага, не стоит. Иначе можно прозевать события, а это плохо. Нет, обработчик то выполнится, но будет это уже не актуально — хороша ложка к обеду. Обязательно погоняй в отладчике код (да хотя бы кучу NOP) с разными прерываниями. Чтобы понять и прочувствовать как ведут себя прерывания. Старая версия статьи. Чисто поржать :) AVR. Учебный курс. Флаги и условные переходы Автор DI HALT Опубликовано 08 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, AVR, Программирование, Флаги Есть в AVR (да и, пожалуй, во всех остальных процессорах) особый регистр SREG. О нем я несколько раз упоминал в прошлых статьях, но не вдавался в подробности. Чтож, пришло время рассказать, что же это жеSREG такой и зачем он нужен. SREG это регистр состояния ядра. Он так называется Status Register. В этом регистре находится независимых битов - флажков. Которые могут быть либо 1 либо 0, в зависимости от выполненных в прошлом операций. И вот по тому какие флаги стоят, можно понять что произошло с процессором и что нам дальше делать. Например, если флаг Z (Zero) выставлен в 1, значит в ходе вычисления предыдущей математической операции в результате образовался ноль. А если выставлен флаг С (Carry - заем, перенос), то мы из меньшего числа отняли большее, или же прибавили такое число, что результат стал больше 255. А теперь подробней по каждому флагу.

  • I - флаг разрешения прерываний. Когда установлен в 1 — прерывания разрешены.
  • T - пользовательский флаг. Можно юзать по своему назначению.

Кроме того, есть две команды которые позволяют в этот бит записать любой бит любого из 32 регистров общего назначения R0-R31 (далее буду их звать РОН). Это команды BLD Rn,bit и BST Rn,bit

  • H - флаг полупереноса. Это если произошел заем бита из старшей половины байта в младшую. То есть когда из числа 0001 0111 пытаются вычести 0000 1000, то происходит заем бита из более старшего разряда, так как младшая тетрада уменьшаемого меньше чем младшей тетрады вычитаемого. Используется этот флаг в некоторых математических операциях.
  • S - флаг знака. 1 - значит минус. При вычислении чисел со знаком он возникает если после арифметической операции возник отрицательный результат. Флаг S = V XOR N.
  • V - Флаг переполнения дополнительного кода. Это если мы считаем число в дополнительном коде со знаком и оно вылезло за пределы регистра.

Число в дополнительном коде с заемом — самая естественная форма представления числа во вселенной! Вот возьмем, например, число -61 как его получить? Ну не знаем мы про отрицательные числа! Просто! Вычтем его из нуля 00 - 61 = 39 Во как! Заняли из старшего разряда! Не похоже, да? Хорошо, проверим столбиком: 61 + 39 – 00 А единичка не влезла в разрядность! ЧТД. (с) Лохов С.П. (Наш преподаватель по ассемблеру в универе) Вот двоичный доп код работает точно по такому же принципу. А в процессоре есть команды для перевода числа из в доп код за одну команду.

  • N - флаг отрицательного значения. Если в результате арифметической операции 7 бит результата стал 1, то этот флаг тоже станет 1.
  • Z - флаг нуля. Если в результате какой либо операции получился ноль, то вылазит этот флаг. Чертовски удобно для всех целей!
  • С - флаг переноса. Если в результате операции произошел выход за границы байта, то выставляется этот флаг. Вообще самый юзаемый флаг после Z и I. Что только с ним не творят, как только не юзают.

Флаги, кроме автоматической установки, можно устанавливать и сбрасывать вручную. Для этого есть команды SE* для установки и CL* для сброса. Вместо звездочки подставляется нужный флаг, например, CLI - запрет прерываний. В даташите, в разделе Instruction Set Summary, написано какая команда что делает и на какие флаги влияет. Пример:

1 2 3 4 5 INC Rd Increment Rd = Rd + 1 Z,N,V DEC Rd Decrement Rd = Rd − 1 Z,N,V TST Rd Test for Zero or Minus Rd = Rd AND Rd Z,N,V CLR Rd Clear Register Rd = Rd XOR Rd Z,N,V SER Rd Set Register Rd = $FF None

Команда INC прибавляет к регистру 1, но несмотря на то, что она может добить регистр до переполнения, флаг переполнения С она не ставит. Такая особенность. Зато она ставит флаги нуля, отрицательного значения и переполнения доп кода. Как инкремент может дать нуль? Элементарно, прибавив к -1 +1. Минус 1 в двоичной знаковой арифметике = FF. FF+1=1 00 ,но 1 не влезла в разрядность, поэтому 00 Логично же? :) Или хотим мы, например, узнать в каком регистре число больше в R17 или R18 Нет ничего проще — к нашим услугам команда CP (нет, не детское порно, а Compare). Эта команда, у себя в уме, из R17 вычитает R18 при этом содержимое регистров не меняется, а меняются только флаги. И если, например, выскочил флаг С, значит при R17-R18 произошел заем, а значит R18 больше R17. Если флаг С не появился, то значит R17 больше чем R18. А коли у нас выскочил нуль, то значения равны. Есть еще команда CPI Rn,### работает также, но сравнивает регистр (только старшую группу) с произвольным числом. Используется чаще.

1 CP R17,R18

А потом смотрим флаги. И дальше в ход вступают команды условных переходов из группы BRANCH (ветвление). BR** И вот в этом месте товарищей из ATMEL надо хватать за ноги и бить головой об стену. Потому что я не понимаю на кой хрен было так все запутывать, изобретая команды которых реально нет? Суди сам. Флагов у нас 8, соответственно должно быть 16 возможных бранчей. 8 по условию — флаг есть, 8 по условию — флага нет. Бранчевых команд же у нас аж 20 штук.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 BRBC # переход если бит # в регистре SREG=0 BRBS # переход если бит # в регистре SREG=1 BRCS переход если С=1 BRCC переход если С=0 BREQ переход если Z=1 BRNE переход если Z=0 BRSH переход если С=0 BRLO переход если С=1 BRMI переход если N=1 BRPL переход если N=0 BRGE переход если S=0 BRLT переход если S=1 BRHC переход если H=0 BRHS переход если H=1 BRTC переход если T=0 BRTS переход если T=1 BRVS переход если V=1 BRVC переход если V=0 BRID переход если I=0 BRIE переход если I=1
  • Если значение = 1, то делаем действие А
  • Если значение = 2, то делаем действие Б
  • А если значение меньше 13, то делаем действие ЦЭ
  • Во всех остальных случаях не делаем ничего
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 CPI R16,1 ; Сравниваем R16 с 1 BREQ ActionA ; Переход если равно (EQual, Z=1) ; Если не равно, то идем дальше CPI R16,2 ; Сравниваем R16 с 2 BREQ ActionB ; Переход если равно ; Если не равно, то идем дальше CPI R16,13 ; Сравниваем R16. т.е. R16-13 BRCS ActionC ; Если возник перенос, значит R16 меньше 13 ; Если не возник - идем дальше RJMP NoAction ; Переход на выход ActionA: NOP NOP ; Делаем наш экшн NOP RJMP NoAction ; Выходим, чтобы не влезть в ActionB ActionB: NOP NOP ; Делаем наш экшн NOP RJMP NoAction ; Выходим, чтобы не влезть в ActionC ActionC: NOP NOP ; Делаем наш экшн NOP NoAction: NOP ; Вместо NOP, разумеется, должны быть какие-нибудь полезные команды.

Сложно? Вот и я думаю, что делать нефиг :))))) Ничуть не сложней чем на Си забабахать из if then конструкцию или switch-case какой-нибудь. Бег по граблям У команд BR*** есть правда весьма ощутимое западло. Дальнобойность их составляет всего 63 команды. Т.е. это относительный переход. Поначалу ты этого не заметишь — короткая программа обычно не допускает переходов дальше 63. Но вот, со временем, твоя программа распухнет, появится дофига кода и дальности бранча перестанет хватать. Вроде бы все работало, а добавил пару команд - и компилятор начал ругаться злыми словами - Error out of range или что то в этом духе. Как быть? Перехватываться через промежуточные переходы. Т.е. находим ближайший к нам безусловный переход за который контроллер, как бы не старался залезть не сможет.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ActionA: NOP NOP NOP RJMP NoAction NOP ; То есть если я вот тут поставлю островок ; то он никогда не выполнится. Т.к. сверху ; Процессор перепрыгнет сразу по RJMP ; А снизу вход будет сразу же на ActionB ActionB: NOP NOP NOP RJMP NoAction И вот, в этом островке, мы создаем капсулу телепортер такого вида: ActionA: NOP NOP NOP RJMP NoAction ;----------------------------------- Near: JMP FarFar_away ;------------------------------------ ActionB: NOP NOP NOP RJMP NoAction

Т.е. бранчу теперь достаточно дострелить до островка Near, а там дальнобойный JMP зашлет его хоть в бутсектор на другой конец флеша. В случае большой программы, чтобы не плодить островки, его лучше сделать один, сразу после пачки CP. Test & Skip Кроме Branch‘ей есть еще один тип команд: проверка — пропуск. Работает она по принципу “Проверяем условие, если справедливо - пропускаем следующую команду” Запомнить просто, первая буква это Skip - пропуск. Вторая условие - С=Clear, т.е. 0 S=Set, т.е. 1. Соответственно S**C пропуск если сброшено. S**S пропуск если установлено. Команды SBRC/SBRS Указываешь ей какой РОН, и какой номер бита в этом регистре надо проверить. И если условие верное, то следующая команда будет пропущена. Пример:

1 2 3 4 5 6 7 8 9 10 11 12 SBRC R16,3 ; Если бит 3 в регистре R16 = 0, то прыжок через команду, на NOP RJMP bit_3_of_R16_Not_Zer0 NOP SBRS R16,3 ; Если бит 3 в регистре R16 = 1, то прыжок через команду, на NOP RJMP bit_3_of_R16_Zer0 NOP

Аналогичная команда SBIC/SBIS Но проверяет она не биты регистров РОН, а биты регистров периферийных устройств. Те самые,что идут в памяти между блоком РОН и оперативкой. Но есть у ней ограничение — она может проверить только первые 1F регистров ввода вывода. Если заглянешь в m16def.inc (для мега16, для других МК в их файл дефайнов) То увидишь там это:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 .equ UBRRH = 0x20 .equ UCSRC = 0x20 .equ EEARL = 0x1e ( .equ EEARH = 0x1f

Вот все это богатство твое. Проверяй не хочу :)))) А мне мало! Я хочу дальше. Что делать. А дальше жизнь наша трудна и опасна. Чуть вправо,чуть влево - взрыв и ошметки. Страшно? На самом деле ничего такого. Просто нам придется заюзать битмаски. И будет это не в одну команду, а в три. Например, надо нам проверить состояние третьего бита в регистре UCSRC. Как видишь, это выше чем 1F Так что тест-скип не прокатит. Не беда, делай как я!

1 2 3 4 5 6 7 8 IN R16, UCSRC ; Хватаем байт из регистра, целиком. ANDI R16,1; Накладываем на него маску 00001000 ; В результате, все байты кроме третьего ; Обнулятся. А третий каким был таким и ; останется. Был нулем - будет нуль и будет Z ; Не был нулем, не будет Z флага. =)))) BREQ Bit_3_of_R16_Equal_Zero

Говорил же в три команды уложимся =) А можно проверять и не по одному биту сразу. Накладывай нужные маски, оставляй только нужные биты. А дальше смотри какие числа эти биты могут образовать и сравнивай напрямую с этими числами через CPI. Красота. Ладно, к битмаскам мы еще не раз вернемся. Это мощнейшее средство, но пока, не влезая в периферию, его не прочуешь. А до периферии мы еще не до росли. Всему свое время. В следующей статье я тебе буду взрывать мозг индексными табличными переходами. Сходи лучше воздухом подыши предварительно. Такие вещи надо раскуривать со свежими мозгами AVR. Учебный курс. Ветвления на индексных переходах Автор DI HALT Опубликовано 08 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, AVR, Таблица переходов, Трюки Таблицы переходов Вот представь, что нам надо сделать мега CASE, когда на вход валится число от 1 до 100 и нам надо сто вариантов действий. Как будешь делать? Если лепить сто штук CPI с последующими переходами, то можно дальше убиться головой об стену. У тебя только эти CPI/BR** сожрут половину памяти кристалла. Учитывая, что каждая CPI это два байта, а каждый BR** еще байт. А о том сколько тактов эта шняга будет выполняться я даже не упоминаю. Делается это все круче. Помнишь я тебе рассказывал в прошлых уроках о таких командах как ICALL и IJMP. Нет, это не новомодная яблочная истерия, а индексный переход. Прикол в том, что переход (или вызов подпрограммы, не важно) осуществляется тут не по метке, а по адресу в регистре Z (о том что Z это пара R30:R31 я пожалуй больше напоминать не буду, пора бы запомнить). Итак, вначале пишем дофига вариантов наших действий. Те самые сто путей, у меня будет не сотня, а всего пять, но это не важно.

1 2 3 4 5 Way0: NOP Way1: NOP Way2: NOP Way3: NOP Way4: NOP

Дальше, где нибудь посреди кода мы херачим таблицу переходов.

1 Table: .dw Way0, Way1, Way2, Way3, Way4

Распологать ее можно где угодно. Хоть прямо тутже, хоть в конце кода. Главное, чтобы программа при исполнении не выполнила эту строку как команды, иначе будет ошибка. Для этого таблицы либо перепрыгивают с помощью команды RJMP

1 2 3 4 5 6 7 RJMP Kudato ; Программа сюда никогда не попадет. Table: .dw Way0, Way1, Way2, Way3, Way4 Kudato: NOP NOP

Или (предпочтительней) размещать в слепых тупиках кода, где выполнение не будет по алгоритму. Например между подпрограммами. Так:

1 2 3 4 5 6 7 8 9 10 . NOP RET ; Точка выхода ; Программа сюда никогда не попадет Table: .dw Way0, Way1, Way2, Way3, Way4 SomeProc: NOP ; Точка входа NOP .

Таблица переходов это всего лишь строка данных в памяти, содержащая адреса Way0…Way4. Обратите внимание на то, что данные у нас двубайтные слова dw. Если же мы хотим адресовать расположенные данные, например вложенную таблицу адресов переходов, то адреса нужно умножать на два. Вообще тут проще при написании по быстрому скомпилить кусок, открыть дамп с map файлом и посмотреть что лежит в памяти, куда что ссылается. Сразу станет понятно надо умножать на два или нет. Допустим у нас данные появляются в регистре R20 и нам, на основании числа там, нужно выбрать по какому пути переходить. Регистр R21 временный, под всякую хрень. А теперь делаем финт ушами.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 LSL R20 ; Сдвигом влево умножаем содержимое R20 на два. ; Было, например, 011=3 стало 110=6 Круто да? ;) ; опять же изза того, что у нас адреса двубайтные ; НЕ ПУТАТЬ С ТЕМ ЧТО КОМПИЛЕР ОБСЧИТЫВАЕТ ; ПАМЯТЬ В СЛОВАХ, тут несколько иное. Если непонятно ; то в комменты пишите, обьясню. LDI ZL, low(Table*2) ; Загружаем адрес нашей таблицы. Компилятор сам посчитает LDI ZH, High(Table*2) ; Умножение и запишет уже результат.Старший и младший байты. CLR R21 ; Сбрасываем регистр R21 - нам нужен ноль. ADD ZL, R20 ; Складываем младший байт адреса. Если возникнет переполнение ADC ZH, R21 ; То вылезет флаг переноса. Вторая команда складывает ; с учетом переноса. Поскольку у нас R21=0, то по сути ; мы прибавляем только флаг переноса. Вопросы - в комменты! ; Таким образом складываются многобайтные числа. ; Позже освещу тему ; Математики на ассемблере. LPM R20,Z+ ; Загрузили в R20 адрес из таблицы LPM R21,Z ; Старший и младший байт MOVW ZH:ZL,r21:r20 ; забросили адрес в Z /* Что это было? А все просто! У нас наше число образовало смещение по таблице переходов. Т.е. когда оно равно 0, то смещение тоже нулевое равное адресу Table, а значит выбирается адрес ячейки где лежит адрес на Way0. Следом за ней в памяти сразу же находится адрес Way1, Разница между ними два байта (так как сами адреса двубайтные). Таким образом, если в R20 будет число 1, то команда LSL умножит его на 2 и будет указан на адрес ячейки с Way1 и так далее. А что же дальше? А дальше, конечно же: */ IJMP ; Обана и переход на наш выбранный Way. Понравилось? ; То ли еще будет :)
  • Поднять резец
  • Опустить резец
  • Включить подачу
  • Включить привод
  • Подать на один шаг вперед
  • Подать на один шаг назад
  • Подать влево
  • Подать вправо.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 BladeUP: NOP NOP NOP NOP RET BladeDN: NOP NOP NOP NOP RET DriveON: NOP NOP NOP NOP RET DriveOFF: NOP NOP NOP NOP RET Forward: NOP NOP NOP NOP RET Back: NOP NOP NOP NOP RET

И так далее, все нужные команды. Затем, также как и в случае индексных переходов, создается таблица с адресами процедур.

1 Index: .dw BladeUP, BladeDN, DriveON, DriveOFF, Forward, Back

А в памяти ОЗУ заводится очередь задач. Обычный строковый массив нужной длины:

1 TaskList: .byte 30

Потом создается процедура которая извне загружает нашу очередь действий, в виде последовательности кодов этих действий (всего лишь смещение по таблице! Очень быстрое и компактное!) и вызывается диспетчер очереди. Диспетчер будет в цикле перебирать нашу строку TaskList, выковыривать из нее номера подпрограмм, по таблице, смещением, вычислять адреса переходов на реальные процедуры, переходить по ним, делать полезное действие, возвращаться обратно и брать новое значение из таблицы. Чуете куда я клоню? Получается своеобразная виртуальная машина. Процессор в процессоре. Более того, сами задачи, вызываемые из очереди, не обязательно должны быть тупо выполняющими конкретное действие. Они же тоже могут набрасывать в эту самую очередь новых кодов, сортировать и на ходу их переделывать. Получается мощный полиморфный алгоритм, который может сам менять свою логику исходя из условий. Позже, я на этом принципе покажу прообраз операционной системы. С диспетчером задач и кучей потоков, вызывающих друг друга по цепочке. А еще на индексных переходах можно делать очень компактные конечные автоматы. Причем даже адрес не надо будет вычислять т.к. в виде текущего состояния можно смело использовать прямые адреса других состояний автомата. Если не понял о чем идет речь, то не забивай пока голову. Дальше будет на это дело отдельная статья =) Или покури интернет на предмет того, что такое конечные автоматы и как они реализуются. AVR. Учебный Курс. Типовые конструкции Автор DI HALT Опубликовано 09 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, Макро язык, Начинающим, Оптимизация, Трюки При написании программ постоянно приходится использовать разные стандартные конструкции вроде циклов, операторов выбора, перехода, сравнения. Всякие там if-then-else или case-switch. В высокоуровневых языках это все уже готово, а на ассемблере приходится изобретать каждый раз заново. Впрочем, такие вещи пишутся один раз, а дальше просто по наезженной тропинке применяются везде, где потребуется. Заодно и оптимизируются по ходу процесса. Условие if-then-else Тут проще всего методом последовательной проверки проложить маршрут до нужного блока кода. Приведу пример:

1 2 3 4 5 6 7 8 9 if (А>=B) < action_a >else < action_b >next_action

Как это проще всего сделать на ассемблере? Считаем, что А в R16,B в R17, а полезные действия, которые могли бы быть там, заменяем на NOP,NOP,NOP. Сравнение делается путем вычитания. По итогам вычитания выставляются флаги. Заем (когда A стало меньше B) означает, что условие не выполнилось.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 CP R16,R17 ; Сравниваем два значения BRCS action_b ; когда A>=B флага С не будет ; Перехода не произойдет action_a: NOP ; и выполнится действие А NOP NOP RJMP next_action ; Но чтобы действие B не произошло ; в ходе естественного выполнения ; кода -- его надо перепрыгнуть. action_b: NOP ; Действие B NOP NOP next_action: NOP NOP NOP

Но надо учитывать тот момент, что в случае А=B флаг С не вылезет, зато будет флаг Z. Но переход то у нас исходя из какого-нибудь одного флага (по С=0 или по С=1). И, исходя из выбора команды для построения конструкции if-then-else (BRCC или BRCS), будет разная трактовка результата условия if (А>=B) в случае А=B. В одном случае (нашем), где переход идет на else по С=1, А=B будет эквивалентно А>B — флага C не будет. И в том и другом случае услове if (А>=B) даст True и переход по BRCS на then. Если перестроить конструкцию наизнанку, через команду BRCC то условия (А>=B) уже не получится. При A=B не будет флага С и произойдет переход по BRCC на else. Для создания строгих неравенств нужна проверка на ноль. Теперь А больше B:

1 2 3 4 5 6 7 8 9 if (А>B) < action_a >else < action_b >next_action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 CP R16,R17 ; Сравниваем два значения BREQ action_b ; Если равно (флаг Z), то переход сразу. ; Потом проверяем второе условие. BRCS action_b ; когда A>B флага С не будет ; Перехода не произойдет action_a: NOP ; и выполнится действие А NOP NOP RJMP next_action ; Но чтобы действие B не произошло ; в ходе естественного выполнения ; кода -- его надо перепрыгнуть. action_b: NOP ; Действие B NOP NOP next_action: NOP NOP NOP

Сложно? Думаю нет. Усложним еще раз наше условие:

1 2 3 4 5 6 7 8 9 if (C else < action_b >next_action

Считаем, что A=R16, B=R17, С=R18

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ;IF CP R16,R18 ; Сравниваем С и А BREQ action_b ; Переход сразу на ELSE если С=А BRCS action_b ; Если А оказалось меньше, то будет С ; и сразу выходим отсюда на else ; Но если C ; Второе условие (A CP R16,R17 ; Сравниваем два значения ; BREQ action_b ; Переход на ELSE если B=А. Команда BREQ специально ; закомментирована -- она тут не нужна. Я ее поставил ; для наглядности. Ведь в случае А=B ; флага С не будет и однозначно будет переход по BRCC. BRCC action_b ; Когда A>B флага С не будет ; А переход по условию С clear сработает. ;THEN action_a: NOP ; Выполнится действие А NOP NOP RJMP next_action ; Но чтобы действие B не произошло ; в ходе естественного выполнения ; кода -- его надо перепрыгнуть. ;ELSE action_b: NOP ; Действие B NOP NOP next_action: NOP NOP NOP

Просто же! Вот так вот, комбинируя условия, можно размотать любую логическую конструкцию. Битовые операции Но, пожалуй, самые распространенные операции в контроллере — битовые. Включить выключить какой-нибудь параметр, инвертировать его, проверить есть или нет. Да масса случаев где это нужно. Основная масса операций идет через битовые маски. Есть замечательные команды SBI и CBI первая ставит указанный бит в порту, вторая сбрасывает. Например: CBI PORT,7 - обнулить 7й бит в регистре ввода-вывода PORT SBI PORT,6 - выставить 6й бит в регистре ввода-вывода PORT Все замечательно, но работают эти команды только в пределах первых 31 адресов в пространстве регистров ввода вывода. Для мега16 это:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 .equ EEARH = 0x1f .equ EEDR = 0x1d .equ EECR = 0x1c .equ PORTA = 0x1b .equ DDRA = 0x1a .equ PINA = 0x19 .equ PORTB = 0x18 .equ DDRB = 0x17 .equ PINB = 0x16 .equ PORTC = 0x15 .equ DDRC = 0x14 .equ PINC = 0x13 .equ PORTD = 0x12 .equ DDRD = 0x11 .equ PIND = 0x10 .equ SPDR = 0x0f .equ SPSR = 0x0e .equ SPCR = 0x0d .equ UDR = 0x0c .equ UCSRA = 0x0b .equ UCSRB = 0x0a .equ UBRRL = 0x09 .equ ACSR = 0x08 .equ ADMUX = 0x07 .equ ADCSRA = 0x06 .equ ADCH = 0x05 .equ ADCL = 0x04 .equ TWDR = 0x03 .equ TWAR = 0x02 .equ TWSR = 0x01 .equ TWBR = 0x00

И ни байтом дальше. А с более старшими адресами — облом. Ну ничего, что нам мешает взять и записать в регистр ввода-вывода (далее РВВ, а то я уже задолбался). Этот бит самому? Только то, что доступ там к порту идет не побитный, а сразу целыми байтами. Казалось бы, в чем проблема? Надо выставить биты 1 и 3 в регистре TWCR, например, взял да записал двоичное число 00001010 и выставил.

1 LDI R16,1
  • Взять старое значение
  • Подправить в нем биты
  • Записать обратно
1 IN R16,TWCR

А установить нужные биты нам поможет битовая маска и операция OR. В результате этой операции, там где в битовой маске были нули будут те же значения, что и раньше. А где в маске 1 возникнут единички.

1 ORI R16,1; Битовая маска 00001010

А затем записать уже измененный байт обратно

1 OUT TWCR,R16

Сброс битов тоже можно сделать через битовую маску, но уже операция AND. И там где мы хотим сбросить нам надо поставить в маске 0, а где не хотим менять 1 Удобней делать инверсную маску. Для инверсии маски применяется операция побитового НЕ ~ Выглядеть будет так:

1 2 3 IN R16,TWCR ANDI R16,~(1<<3|1<<1) OUT TWCR,R16

Обрати внимание, для сброса у нас внутри конструкции используется 1. Ведь байт то потом инвертируется! Для инверсии битов применяется маска по XOR. Нули в этой маске не меняют биты, а единичка по XOR бит инвертирует. Смотри сам, вверху произвольное число, внизу маска:

1 2 3 4 1100 1100 XOR 1111 0000 _________ 0011 1100

Правда есть одно ограничение — нет команды XOR маски по числу, поэтому через регистр.

1 2 3 4 IN R17,TWCR LDI R16, 3; Маска EOR R17,R16 ; Ксорим OUT TWCR,R17 ; Сгружаем обратно

Можно увязать всю ботву в макросы и тогда будет совсем хорошо :) Единственно, при использовании макросов, особенно когда они содержат внутри промежуточные регистры, нельзя забывать про эти регистры. А то в ходе исполнения макроса содержимое этих регистров меняется и если про это забыть можно получить кучу глюков :) Но от такой напасти можно и защититься, например стеком. К примеру, изобретем мы свою команду XRI — XOR регистра с числом. Макрос может быть таким:

1 2 3 4 .MACRO XRI LDI @2,@1 EOR @0,@2 .ENDM

А вызов макроса

1 XRI R16,mask,R17

Последний параметр - промежуточный регистр. Указываем его вручную т.к. мало ли какой из регистров нам будет удобней в данный момент. А можно сделать с прогрузом стека, тогда промежуточные регистры вообще не нужны. Но будет выполняться дольше, занимать больше памяти и требовать стек.

1 2 3 4 5 6 .MACRO XRI PUSH R16 LDI R16,@1 EOR @0,R16 POP R16 .ENDM

Вызов, в этом случае

1 XRI R17,Mask

Но нельзя будет поксорить R16, т.к. его значение все равно затрет при выгрузке из стека. Также масками можно смело отрезать неиспользованные биты. Например, в регистре TWSR первые два бита это настройки, а остальные — код состояние интерфейса TWI. Так зачем нам эти два бита настройки каждый раз учитывать? Отдавили их по AND через маску 11111100 да дело в шляпе. Или сдвинули вправо. Сдвиги Ну тут просто — можно двигать биты в РОН влево и вправо. Причем сдвиг бывает двух типов. LSR Rn - логический вправо, при этом слева в байт лезут нули. LSL Rn - логический влево, при этом справа в байт лезут нули. и через перенос. ROL и ROR При этом байт уходящий за край попадает в флаг С, а флаг С вылезает с другого края байта. Получается как бы 9 битная циклическая карусель. Где одна команда дает один шаг влево или вправо. Как применить? Ну способы разные, например, посчитать число единиц в байте. Смотри как просто:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CLR R18 ; Сюда будем считать единички. Сбросим пока LDI R17,9 ; Счетчиком циклов будет LDI R16,0xAA ; В этом байте будем считать единички CLC ; Сбросим флаг С, чтобы не мешался. Loop: DEC R17 ; уменьшим счетчик BREQ End ; если весь байт дотикали - выход. ROL R16 ; Сдвигаем байт BRCC Loop ; если нет 1 в С, еще одну итерацию INC R18 ; Сосчтитали единичку RJMP Loop End: NOP

Еще через флаг С удобно проверять крайние биты, по быстрому, чтобы не заморачиваться с масками (хотя выигрыша ни по времени, ни по коду не будет).

1 2 ROL R16 BRCS Label ; Переход если бит 7 в R16 есть.
1 2 ROR R16 BRCS Laber ; Переход если бит 0 в R16 есть.

Циклы Ну тут все просто — либо сначала, либо потом условие, а затем тело цикла и все окольцовано переходами. Например, выполнить цикл 20 раз.

1 2 3 4 5 6 7 8 9 10 LDI R17,20 ; Счетный регистр Loop: NOP NOP NOP NOP NOP DEC R17 ; Уменьшаем счетчик BRNE Loop

; Переход если не ноль (нет флага Z) Главное следить за тем, чтобы счетный регистр нигде не запоролся в теле цикла. Иначе получим глюк. Такой глюк, конечно, легко вылавливается трассировкой, но далеко не факт, что он всплывает сразу. Еще один пример цикла - тупые задержки. Почему я их называю тупыми? Да потому, что они сами ничего не делают и другим не дают. Крайне не рекомендую их использовать, но для простеньких программ подойдет. Основная идея такой задержки загрузить контроллер бессмысленной работой, чтобы нащелкать как можно больше тактов. У каждого такта есть своя длительность, так что длительность задержки можно формировать от микросекунд, до десятков лет. Вот решение в лоб:

1 2 3 LDI R16, Delay Loop: DEC R16 BRNE loop

Процессор потратит примерно Delay*2 тактов на бессмысленные операции. При длительности такта (на 8мгц) 1.25Е-7 секунд максимальная выдержка будет 6.4E-5 секунды. Немного, но, например, хватит на то чтобы дисплей прожевал отданый ему байт и не подавился следующим. Если надо больше задержки, то делаются вложенные циклы с несколькими счетчиками. Тогда суммарная длительность выдержки перемножается и уже на трех вложенных циклах можно получить около 2 секунд. Ну, а на четырех уже 536 секунд. Но есть более красивое решение, нежели вложенные циклы — вычитание многобайтного числа с переносом.

1 2 3 4 5 6 7 8 9 LDI R16,LowByte ; Грузим три байта LDI R17,MidleByte ; Нашей выдержки LDI R18,HighByte loop: SUBI R16,1 ; Вычитаем 1 SBCI R17,0 ; Вычитаем только С SBCI R18,0 ; Вычитаем только С BRCC Loop ; Если нет переноса - переход.
  • Делаем раз
  • Делаем два
  • Делаем три
  • Тупим
  • Делаем то, ради чего тупили
  • Делаем четыре
  • Делай раз
  • Делай два
  • Делай три
  • Тик!
  • Натикало? -да- Делаем то, ради чего тупили сбрасываем счетчик.
  • Делай четыре
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 .DSEG Counter: .byte 3 ; Наш счетчик циклов. Три байта. .CSEG MainLoop: Do_One: NOP Do_Two: NOP Do_Three: NOP LDS R16,Counter ; Грузим наш счетчик LDS R17,Counter+1 LDS R18,Counter+2 SUBI R16,1 ; Вычитаем 1 SBCI R17,0 ; Вычитаем только С SBCI R18,0 ; Вычитаем только С BRCC DoNothing ; Не натикало? Переход ; Натикало! YES: NOP ; Делаем то, ради чего тупили NOP NOP LDI R16,LowByte ; Грузим три байта LDI R17,MidleByte ; Нашей выдержки LDI R18,HighByte DoNothing: STS Counter,R16 ; Сохраняем обратно в память STS Counter+1,R17 STS Counter+2,R18 RJMP MainLoop

Обрати внимание, что другие операции Do_one, Do_Two, Do_Three не ждут когда натикают, они выполняются в каждую итерацию. А операция требующая задержку ее получает, не тормозя всю программу! И таких таймеров можно налепить сколько угодно, пока оперативка не кончится. Более того, такой цикловой счетчик сам может быть алгоритмозадающим механизмом. Счетчик тикает каждый прогон главного цикла, а каждая операция в этом главном цикле ждет именно своего “номера” в главном счетчике. Получается этакая программная “шарманка”, где в качестве барабана с гвоздями выступает наш счетчик. Но это уже конечные автоматы. К ним я, возможно, вернусь позже. Еще не решил стоит освещать эту тему. А то могу и увлечься. люблю я их :) Горыныч Писал я тут библиотечку для подключения LCD к AVR. А чтобы не вкуривать в команды контроллера дисплея я распотрошил Сишный код, дабы подглядеть какими байтами и в каком порядке надо кормить контроллер, чтобы он вышел на нужный режим. Попутно сварганил один прикольный трюк, который я называю Горыныч. Это когда мы несколько функций объединяем в одну многоголовую - с несколькими точками входа и одной точкой выхода. Итак, мы имеем две функции обращения к LCD - запись данных и запись команд. О! Вот эти ребята:

1 2 3 4 5 6 7 8 9 10 11 12 13 CMD_WR: CLI RCALL BusyWait CBI CMD_PORT,RS CBI CMD_PORT,RW SBI CMD_PORT,E LCD_PORT_OUT OUT DATA_PORT,R17 RCALL LCD_Delay CBI CMD_PORT,E LCD_PORT_IN SEI RET

Нененененене Девид Блейн.

1 2 3 4 5 6 7 8 9 10 11 12 13 DATA_WR: CLI RCALL BusyWait SBI CMD_PORT,RS CBI CMD_PORT,RW SBI CMD_PORT,E LCD_PORT_OUT OUT DATA_PORT,R17 RCALL LCD_Delay CBI CMD_PORT,E LCD_PORT_IN SEI RET

Сейчас я вам покажу особую, оптимизаторскую, магию!

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 CMD_WR: CLI RCALL BusyWait CBI CMD_PORT,RS RJMP WR_END DATA_WR: CLI RCALL BusyWait SBI CMD_PORT,RS WR_END: CBI CMD_PORT,RW SBI CMD_PORT,E LCD_PORT_OUT OUT DATA_PORT,R17 RCALL LCD_Delay CBI CMD_PORT,E LCD_PORT_IN SEI RET

Ты что наделал Блейн. Ты зачем функцию скукожил. Нука раскукожь ее обратно! У меня теперь функция беби сайз. Ну, а теперь, для сравнения, поглядим как это сделано в LCD.c весь исходник я сюда копировать не буду, только то, что сделано у меня, ну и всю условную компиляцию я тоже выкину.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void lcdControlWrite(u08 data) < lcdBusyWait(); cbi(LCD_CTRL_PORT, LCD_CTRL_RS); cbi(LCD_CTRL_PORT, LCD_CTRL_RW); sbi(LCD_CTRL_PORT, LCD_CTRL_E); outb(LCD_DATA_DDR, 0xFF); outb(LCD_DATA_POUT, data); LCD_DELAY; LCD_DELAY; cbi(LCD_CTRL_PORT, LCD_CTRL_E); outb(LCD_DATA_DDR, 0x00); outb(LCD_DATA_POUT, 0xFF); >void lcdDataWrite(u08 data)

Собственно, строчка в строчку — те же яйца только в профиль. Что подтверждает, сказанный мной в первом посте, тезис, что не важно на каком языке писать, на си или на ассемблере — главное знать что в какие порты пихать. Но на асме я могу свернуть свою прогу почти вдвое, не потеряв ни байта и ни такта, а на сях придется для этого вводить внутреннию функцию, которая захавает оперативку на стек, потребует кучу тактов на переходы и вообще будет выглядеть убого. И финальная процедура инициализации на сях и на макроасме:

1 2 3 4 5 6 7 8 9 10 void lcdInit()

Ну и у меня:

1 2 3 4 5 6 7 8 .MACRO INIT_LCD RCALL InitHW WR_CMD 0x38 WR_CMD 0x01 WR_CMD 0x06 WR_CMD 0x0F WR_CMD 0x02 .ENDM

Конструкции вида (1<без снижения читабельности. Конечно что либо крупное, вроде того же USB я на Асме делать не буду, тут проще взять готовый код. Хотя… чем черт не шутит, может заморочусь и напишу свой крошечный USB драйвер. AVR. Учебный курс. Стартовая инициализация Автор DI HALT Опубликовано 09 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, Мелочи, Программирование Инициализация памяти Мало кто подозревает о том, что при включении в оперативке далеко не всегда все байты равны 0xFF. Они могут, но не обязаны. Равно как и регистры РОН не всегда равны нулю при запуске. Обычно да, все обнулено, но я несколько раз сталкивался со случаями когда после перезапуска и/или включения-выключения питания, микроконтроллер начинал творить не пойми что. Особнно часто возникает когда питание выключаешь, а потом, спустя некоторое время, пара минут, не больше, включаешь. А всему виной остаточные значения в регистрах. Итак, возьмите себе за правило после каждого включения, в разделе инициализации, еще даже до инициализации стека, делать зануление памяти и очистку всех регистров. Разумеется делается это все в цикле. Вот примерный вариант кода:

1 2 3 4 5 6 7 8 9 10 11 12 RAM_Flush: LDI ZL,Low(SRAM_START) ; Адрес начала ОЗУ в индекс LDI ZH,High(SRAM_START) CLR R16 ; Очищаем R16 Flush: ST Z+,R16 ; Сохраняем 0 в ячейку памяти CPI ZH,High(RAMEND+1) ; Достигли конца оперативки? BRNE Flush ; Нет? Крутимся дальше! CPI ZL,Low(RAMEND+1) ; А младший байт достиг конца? BRNE Flush CLR ZL ; Очищаем индекс CLR ZH

Поскольку адрес оперативки у нас двубайтный, то мы вначале смотрим, чтобы старший байт совпал с концом, а потом добиваем оставшиеся 255 байт в младшем байте адреса. Далее убиваем все регистры от первого до последнего. Все, контроллер готов к работе.

1 2 3 4 5 LDI ZL, 30 ; Адрес самого старшего регистра CLR ZH ; А тут у нас будет ноль DEC ZL ; Уменьшая адрес ST Z, ZH ; Записываем в регистр 0 BRNE PC-2 ; Пока не перебрали все не успокоились

За процедурку зануления регистров спасибо Testicq Либо значения сразу же инициализируются нужными величинами. Но, обычно, я от нуля всегда пляшу. Поэтому зануляю все. З.Ы. Кстати, о оперативке. Нашел я недавно планку оперативной памяти на 1килобайт, древнюю как говно мамонта, еще на ферромагнитных кольцах. AVR. Учебный курс. Скелет программы Автор DI HALT Опубликовано 10 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, AVR, Макро язык, Программирование, Трюки, Флаги При написании прошивки надо очень внимательно подходить к процессу организации архитектуры будущей программы. Программа должна быть быстрой, не допускать задержек главного цикла и легко расширяться. Оптимально использовать аппаратные ресурсы и стараться выжать максимум возможного из имеющихся ресурсов. Вообще, архитектура программ это отдельная тема и ближе к концу курса, в его Сишной части я подробней рассказываю о разных типах организации прошивки. Можешь забежать вперед и поглядеть, что да как. В ассемблерной же части, я расскажу о одном из самых простых вариантов — флаговом автомате, а позже, когда ты уже будешь вовсю ориентироваться в моем коде, дам пример на основе конвейерного диспетчера, с подробным описанием его работы. Суперцикл Все программы на микроконтроллерах обычно зацикленные. Т.е. у нас есть какой то главный цикл, который вращается непрерывно. Структура же программы при этом следующая:

  • Макросы и макроопредения
  • Сегмент ОЗУ
  • Точка входа - ORG 0000
  • Таблица векторов - и вектора, ведущие в секцию обработчиков прерываний
  • Обработчики прерываний - тела обработчиков, возврат отсюда только по RETI
  • Инициализация памяти - а вот уже отсюда начинается активная часть программы
  • Инициализация стека
  • Инициализация внутренней периферии - программирование и запуск в работу всяких таймеров, интерфейсов, выставление портов ввода-вывода в нужные уровни. Разрешение прерываний.
  • Инициализация внешней периферии - инициализация дисплеев, внешней памяти, разных аппаратных примочек, что подключены к микроконтроллеру извне.
  • Запуск фоновых процессов - процессы работающие непрерывно, вне зависимости от условий. Такие как сканирование клавиатуры, обновление экрана и так далее.
  • Главный цикл - тут уже идет вся управляющая логика программы.
  • Сегмент ЕЕПРОМ

Начинается все с макросов, их пока не много, если что по ходу добавим.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 .include "m16def.inc" ; Используем ATMega16 ;= Start macro.inc ======================================== .macro OUTI LDI R16,@1 .if @0 < 0x40 OUT @0,R16 .else STS @0,R16 .endif .endm .macro UOUT .if @0 < 0x40 OUT @0,@1 .else STS @0,@1 .endif .endm ;= End macro.inc =======================================

В оперативке пока ничего не размечаем. Нечего.

1 2 3 ; RAM =================================================== .DSEG ; END RAM ===============================================

С точкой входа и таблицей векторов все понятно, следуя нашему давнему шаблону, берем его оттуда:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ; FLASH ====================================================== .CSEG .ORG $000 ; (RESET) RJMP Reset .ORG $002 RETI ; (INT0) External Interrupt Request 0 .ORG $004 RETI ; (INT1) External Interrupt Request 1 .ORG $006 RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match .ORG $008 RETI ; (TIMER2 OVF) Timer/Counter2 Overflow .ORG $00A RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event .ORG $00C RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A .ORG $00E RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B .ORG $010 RETI ; (TIMER1 OVF) Timer/Counter1 Overflow .ORG $012 RETI ; (TIMER0 OVF) Timer/Counter0 Overflow .ORG $014 RETI ; (SPI,STC) Serial Transfer Complete .ORG $016 RETI ; (USART,RXC) USART, Rx Complete .ORG $018 RETI ; (USART,UDRE) USART Data Register Empty .ORG $01A RETI ; (USART,TXC) USART, Tx Complete .ORG $01C RETI ; (ADC) ADC Conversion Complete .ORG $01E RETI ; (EE_RDY) EEPROM Ready .ORG $020 RETI ; (ANA_COMP) Analog Comparator .ORG $022 RETI ; (TWI) 2-wire Serial Interface .ORG $024 RETI ; (INT2) External Interrupt Request 2 .ORG $026 RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match .ORG $028 RETI ; (SPM_RDY) Store Program Memory Ready .ORG INT_VECTORS_SIZE ; Конец таблицы прерываний

Обработчики пока тоже пусты, но потом добавим

1 2 ; Interrupts ============================================== ; End Interrupts ==========================================

Инициализация ядра. Память, стек, регистры:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 Reset: LDI R16,Low(RAMEND) ; Инициализация стека OUT SPL,R16 ; Обязательно. LDI R16,High(RAMEND) OUT SPH,R16 ; Start coreinit.inc RAM_Flush: LDI ZL,Low(SRAM_START) ; Адрес начала ОЗУ в индекс LDI ZH,High(SRAM_START) CLR R16 ; Очищаем R16 Flush: ST Z+,R16 ; Сохраняем 0 в ячейку памяти CPI ZH,High(RAMEND) ; Достигли конца оперативки? BRNE Flush ; Нет? Крутимся дальше! CPI ZL,Low(RAMEND) ; А младший байт достиг конца? BRNE Flush CLR ZL ; Очищаем индекс CLR ZH CLR R0 CLR R1 CLR R2 CLR R3 CLR R4 CLR R5 CLR R6 CLR R7 CLR R8 CLR R9 CLR R10 CLR R11 CLR R12 CLR R13 CLR R14 CLR R15 CLR R16 CLR R17 CLR R18 CLR R19 CLR R20 CLR R21 CLR R22 CLR R23 CLR R24 CLR R25 CLR R26 CLR R27 CLR R28 CLR R29 ; End coreinit.inc

Всю эту портянку можно и нужно спрятать в inc файл и больше не трогать. Секции внешней и внутренней инициализации переферии пока пусты, но ненадолго. Равно как и запуск фоновых программ. Потом я просто буду говорить, что мол добавьте эту ботву в секцию Internal Hardware Init и все :)

1 2 3 4 5 6 7 8 9 10 11 ; Internal Hardware Init ====================================== ; End Internal Hardware Init =================================== ; External Hardware Init ====================================== ; End Internal Hardware Init =================================== ; Run ========================================================== ; End Run ======================================================

А теперь, собственно, сам главный цикл.

1 2 3 4 5 ; Main ========================================================= Main: JMP Main ; End Main =====================================================

Все процедуры располагаются в отдельной секции, не смешиваясь с главным циклом. Так удобней, потом можно их по частям вынести в библиотечные файлы и разделить исходник на несколько файлов. Но мы пока это делать не будем. Разделим их просто логически.

1 2 3 ; Procedure ==================================================== ; End Procedure ================================================

Ну и вот тебе файлик с уже готовым проектом под этот шаблон AVR. Учебный курс. Операционная система. Пример. Автор DI HALT Опубликовано 10 июля 2008 Рубрики: AVR. Учебный курс Метки: Assembler, AVR, RTOS, Программирование, Трюки Отлично, с теорией работы ОС ознакомил. Устанавливать научил, осталось научить использовать весь этот конвеерно таймерный шухер. Чем я сейчас и займусь. Сразу берем быка за рога и формулируем учебно-боевую программу. Тестовое задание: Пусть у нас будет ATMega8, с несколькими кнопками. АЦП и подключеним к компу через UART. На меге будет три светодиода.

  • Девайс должен при включении начинать мигать зеленым диодом, мол работаю.
  • При этом раз в секунду сканировать показания АЦП и если показания ниже порога - Моргать красным диодом.
  • По сигналу с UARТ с целью защиты от ошибок сделать по байту ‘R’ установку флага готовности, а потом, в течении 10ms если не придет байт ‘A’ сбросить флаг готовности и игнорировать все входящие байты кроме ‘R’. Если ‘A’ придет в течении 10мс после ‘R’, то отправить в UART ответ и зажечь белый диод на 1 секунду.

Вот так вот, не сильно сложно. Но мне просто лень делать что либо сложней, а для тестовой задачи сгодится. Итак, что у нас есть: Две фоновые задачи, которые выполняются всегда и постоянно:

  • Мигать зеленым диодом
  • Проверять показания с АЦП

И цепочки:

  • Прерывание АЦП - Проверка условия - зажечь диод - погасить диод.
  • Прерывание UART- Проверить на R - взвести флаг (ждать ‘А’ - зажеть диод - погасить диод) - снять флаг

Чем отличаются команды ret и reti

Acrobat Distiller 7.0 (Windows)

2006-12-28T13:15:43+05:00 Acrobat PDFMaker 7.0 for Word 2006-12-28T13:18:27+05:00 2006-12-28T13:18:27+05:00 uuid:06faada1-0f64-42de-bdc6-eaa63e698ecb uuid:1b537dab-2677-4527-b118-c9a62a5751d9 24 application/pdf ИЗУЧЕНИЕ СИСТЕМЫ КОМАНД Semen

endstream endobj 356 0 obj > endobj xref 0 3473 0000000000 65535 f 0000056014 00000 n 0000056268 00000 n 0000058119 00000 n 0000058386 00000 n 0000061332 00000 n 0000061626 00000 n 0000061906 00000 n 0000065206 00000 n 0000065488 00000 n 0000065536 00000 n 0000066308 00000 n 0000066592 00000 n 0000072008 00000 n 0000072292 00000 n 0000077045 00000 n 0000077329 00000 n 0000081998 00000 n 0000082307 00000 n 0000087297 00000 n 0000087670 00000 n 0000090795 00000 n 0000090939 00000 n 0000097430 00000 n 0000097751 00000 n 0000100048 00000 n 0000100320 00000 n 0000115001 00000 n 0000115349 00000 n 0000118264 00000 n 0000118684 00000 n 0000131329 00000 n 0000131677 00000 n 0000136064 00000 n 0000136162 00000 n 0000140477 00000 n 0000140825 00000 n 0000145389 00000 n 0000145487 00000 n 0000148852 00000 n 0000149136 00000 n 0000154810 00000 n 0000155094 00000 n 0000160653 00000 n 0000160937 00000 n 0000166565 00000 n 0000166938 00000 n 0000170661 00000 n 0000170852 00000 n 0000172913 00000 n 0000173280 00000 n 0000174643 00000 n 0000174815 00000 n 0000176894 00000 n 0000177046 00000 n 0000179142 00000 n 0000179343 00000 n 0000181541 00000 n 0000181935 00000 n 0000182958 00000 n 0000183271 00000 n 0000186793 00000 n 0000186976 00000 n 0000191021 00000 n 0000191190 00000 n 0000192990 00000 n 0000193384 00000 n 0000195317 00000 n 0000195634 00000 n 0000198446 00000 n 0000198627 00000 n 0000203571 00000 n 0000203714 00000 n 0000204527 00000 n 0000204900 00000 n 0000209054 00000 n 0000209246 00000 n 0000211453 00000 n 0000211735 00000 n 0000216972 00000 n 0000217281 00000 n 0000221645 00000 n 0000221927 00000 n 0000226118 00000 n 0000226491 00000 n 0000230634 00000 n 0000230838 00000 n 0000232830 00000 n 0000233203 00000 n 0000236597 00000 n 0000236740 00000 n 0000242172 00000 n 0000242456 00000 n 0000246635 00000 n 0000246892 00000 n 0000251547 00000 n 0000251804 00000 n 0000253494 00000 n 0000253778 00000 n 0000258119 00000 n 0000258377 00000 n 0000262881 00000 n 0000263167 00000 n 0000267312 00000 n 0000267571 00000 n 0000271875 00000 n 0000272134 00000 n 0000273482 00000 n 0000273768 00000 n 0000277686 00000 n 0000277972 00000 n 0000281825 00000 n 0000282084 00000 n 0000285021 00000 n 0000285280 00000 n 0000287800 00000 n 0000288084 00000 n 0000290276 00000 n 0000301097 00000 n 0000301378 00000 n 0000319193 00000 n 0000319474 00000 n 0000319792 00000 n 0000320147 00000 n 0000320289 00000 n 0000320973 00000 n 0000321329 00000 n 0000321825 00000 n 0000364252 00000 n 0000364520 00000 n 0000364787 00000 n 0000401011 00000 n 0000408450 00000 n 0000408681 00000 n 0000408981 00000 n 0000409175 00000 n 0000409308 00000 n 0000409458 00000 n 0000409610 00000 n 0000409663 00000 n 0000409716 00000 n 0000409769 00000 n 0000409822 00000 n 0000409875 00000 n 0000409928 00000 n 0000409981 00000 n 0000410034 00000 n 0000410087 00000 n 0000410239 00000 n 0000410390 00000 n 0000410541 00000 n 0000410594 00000 n 0000410647 00000 n 0000410700 00000 n 0000410753 00000 n 0000410806 00000 n 0000410958 00000 n 0000411110 00000 n 0000411262 00000 n 0000411315 00000 n 0000411368 00000 n 0000411520 00000 n 0000411672 00000 n 0000411824 00000 n 0000411877 00000 n 0000411930 00000 n 0000411983 00000 n 0000412135 00000 n 0000412286 00000 n 0000412339 00000 n 0000412491 00000 n 0000412643 00000 n 0000412696 00000 n 0000412848 00000 n 0000413000 00000 n 0000413152 00000 n 0000413205 00000 n 0000413356 00000 n 0000413409 00000 n 0000413462 00000 n 0000413612 00000 n 0000413764 00000 n 0000413916 00000 n 0000413969 00000 n 0000414118 00000 n 0000414270 00000 n 0000414422 00000 n 0000414571 00000 n 0000414723 00000 n 0000414776 00000 n 0000414829 00000 n 0000414981 00000 n 0000415034 00000 n 0000415079 00000 n 0000415231 00000 n 0000415383 00000 n 0000415535 00000 n 0000415687 00000 n 0000415740 00000 n 0000415793 00000 n 0000415945 00000 n 0000415998 00000 n 0000416051 00000 n 0000416104 00000 n 0000416157 00000 n 0000416210 00000 n 0000416360 00000 n 0000416413 00000 n 0000416466 00000 n 0000416616 00000 n 0000416766 00000 n 0000416918 00000 n 0000417068 00000 n 0000417290 00000 n 0000419960 00000 n 0000420006 00000 n 0000420042 00000 n 0000420088 00000 n 0000420134 00000 n 0000420179 00000 n 0000420224 00000 n 0000420270 00000 n 0000420827 00000 n 0000421086 00000 n 0000442746 00000 n 0000443087 00000 n 0000443345 00000 n 0000463915 00000 n 0000464054 00000 n 0000464305 00000 n 0000464351 00000 n 0000464397 00000 n 0000464443 00000 n 0000464489 00000 n 0000464535 00000 n 0000464581 00000 n 0000464627 00000 n 0000464673 00000 n 0000464719 00000 n 0000464765 00000 n 0000464811 00000 n 0000464857 00000 n 0000465006 00000 n 0000465180 00000 n 0000465251 00000 n 0000465378 00000 n 0000465554 00000 n 0000465737 00000 n 0000465790 00000 n 0000465881 00000 n 0000465934 00000 n 0000466066 00000 n 0000466119 00000 n 0000466243 00000 n 0000466296 00000 n 0000466461 00000 n 0000466633 00000 n 0000466686 00000 n 0000466835 00000 n 0000467047 00000 n 0000467191 00000 n 0000467244 00000 n 0000467359 00000 n 0000467491 00000 n 0000467544 00000 n 0000467720 00000 n 0000467773 00000 n 0000467923 00000 n 0000467976 00000 n 0000468029 00000 n 0000468212 00000 n 0000468327 00000 n 0000468380 00000 n 0000468489 00000 n 0000468621 00000 n 0000468674 00000 n 0000468849 00000 n 0000468996 00000 n 0000469049 00000 n 0000469176 00000 n 0000469229 00000 n 0000469393 00000 n 0000469446 00000 n 0000469592 00000 n 0000469645 00000 n 0000469698 00000 n 0000469751 00000 n 0000469883 00000 n 0000469936 00000 n 0000470068 00000 n 0000470121 00000 n 0000470261 00000 n 0000470314 00000 n 0000470448 00000 n 0000470501 00000 n 0000470554 00000 n 0000470667 00000 n 0000470720 00000 n 0000470851 00000 n 0000470904 00000 n 0000471034 00000 n 0000471087 00000 n 0000471233 00000 n 0000471286 00000 n 0000471339 00000 n 0000471392 00000 n 0000471563 00000 n 0000471616 00000 n 0000471833 00000 n 0000471886 00000 n 0000472078 00000 n 0000472131 00000 n 0000472333 00000 n 0000472386 00000 n 0000472439 00000 n 0000472492 00000 n 0000472545 00000 n 0000477737 00000 n 0000479815 00000 n 0000480966 00000 n 0000482207 00000 n 0000483799 00000 n 0000484934 00000 n 0000485995 00000 n 0000487413 00000 n 0000488466 00000 n 0000490133 00000 n 0000491203 00000 n 0000492293 00000 n 0000493358 00000 n 0000494905 00000 n 0000495996 00000 n 0000497133 00000 n 0000498227 00000 n 0000499856 00000 n 0000500985 00000 n 0000502079 00000 n 0000503188 00000 n 0000504619 00000 n 0000506068 00000 n 0000507529 00000 n 0000508824 00000 n 0000510491 00000 n 0000512175 00000 n 0000513832 00000 n 0000515104 00000 n 0000516306 00000 n 0000517923 00000 n 0000518417 00000 n 0000518454 00000 n 0000518479 00000 n 0000518558 00000 n 0000518688 00000 n 0000518820 00000 n 0000518952 00000 n 0000519092 00000 n 0000523492 00000 n 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f 0000000000 65535 f trailer > startxref 116 %%EOF

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *