Результат Глава 1. Передача данных — КиберПедия 

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...

Результат Глава 1. Передача данных

2023-02-03 19
Результат Глава 1. Передача данных 0.00 из 5.00 0 оценок
Заказать работу

 

Арифметика

Один из регистров, встроенных в 6510, - это регистр состояния процессора (P). Это 8-битный (1 байт) регистр, но используются только 7 бит.


N = отрицательный (1 = отрицательный) Negative (1 = Negative)
V = переполнение (1 = переполнение) Overflow (1 = Overflow)
B = команда прерывания (1 = прерывание, вызванное прерыванием) Break Instruction (1 = Break caused interrupt)
D = десятичный режим (1 = десятичный режим) Decimal Mode (1 = Decimal mode)
I = IRQ отключено (1 = IRQ отключено) IRQ Disable (1 = IRQ disabled)
Z = ноль (1 = нулевой результат) Zero (1 = Result zero)
C = переносить (1 = переносить) Carry (1 = Carry)

 

Многие инструкции сборки устанавливают (в 1) или сбрасывают эти биты (в 0), чтобы будущие инструкции могли принимать решения на основе результата, проверяя их статус. Использование этих битов будет рассмотрено по мере необходимости.

В 6510 встроена поддержка сложения с помощью инструкции «ADC» (сложение с переносом) и вычитания с помощью инструкции «SBC» (вычитание с переносом). Нет встроенной поддержки умножения или деления. Можно выполнить полное умножение или деление, используя сложную последовательность инструкций, но это не требуется для игры «Бар на пляже» и поэтому выходит за рамки данной книги.

Бит 0 регистра состояния процесса - это флаг переноса (C). Его можно сбросить (до 0) с помощью команды «CLC» (Clear Carry) и установить (в 1) с помощью команды «SEC» (Set Carry). Другие инструкции также устанавливают и сбрасывают флаг переноса, чтобы указать конкретный результат операции.

Команда «ADC» (сложить с переносом) складывает 8-битное значение аккумулятора, 8-битное значение в ячейке памяти и 1-битное значение во флаге переноса и сохраняет результат обратно в аккумулятор.

 

                                           ADC


Если результат больше 255 (наибольшее значение, которое может быть сохранено в одном байте), устанавливается флаг переноса, в противном случае флаг переноса сбрасывается. Использование флага переноса таким образом позволяет объединить несколько инструкций «ADC» в цепочку для многобайтового сложения (пример 16-разрядного сложения см. В главе «Справочник по макросам»).

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

ВНИМАНИЕ! Не забудьте очистить флаг переноса перед добавлением.


                                           SBC

 

Если большее число вычитается из меньшего, флаг переноса очищается, в противном случае устанавливается флаг переноса. Их также можно объединить в цепочку для многобайтового вычитания (пример 16-битного вычитания см. В главе «Справочник по макросам»).

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

ВНИМАНИЕ! Не забудьте установить флаг переноса перед вычитанием.


Есть способ выполнить быстрое умножение или деление с определенными ограничениями, используя инструкции сдвига и поворота 6510. Они сдвигают двоичные биты в байте на одну позицию влево или вправо, что приводит к умножению или делению значения на 2. Следовательно, повторение этого несколько раз приведет к умножению или делению на 2, 4, 8, 16 и т. д.

Команда «ASL» (арифметический сдвиг влево) сдвигает все биты в позиции аккумулятора 1 влево. 0 сдвигается в бит 0, а бит 7 сдвигается во флаг переноса.

                                           ASL

 

Команда «LSR» (логический сдвиг вправо) сдвигает все биты в позиции аккумулятора 1 вправо. 0 сдвигается в бит 7, а бит 0 сдвигается во флаг переноса.


                                           LSR

 

Команда «ROL» (ROtate Left) сдвигает все биты в позиции аккумулятора 1 влево. Флаг переноса сдвигается в бит 0, а бит 7 сдвигается в флаг переноса.


                                           ROL

 

Команда «ROR» (ROtate Right) сдвигает все биты в позиции аккумулятора 1 вправо. Флаг переноса сдвигается в бит 7, а бит 0 сдвигается в флаг переноса.


                                           ROR

 

Команды сдвига и поворота также изменяют флаги N (отрицательный) и Z (ноль) в регистре состояния процессора. Если 1 сдвигается в бит 7, устанавливается флаг N, в противном случае он сбрасывается. Если значение аккумулятора после сдвига становится равным нулю, устанавливается флаг Z, в противном случае он сбрасывается.

ВНИМАНИЕ! «ASL» против «ROL» и «LSR» против «ROR» немного отличаются.

У 6510 есть альтернативный режим работы для арифметики, называемый двоично-десятичным (BCD). При нормальной работе 6510 интерпретирует байт как значение от 0 до 255. В режиме BCD каждый байт состоит из двух 4-битных полубайтов. Каждый из этих двух полубайтов может хранить значение от 0 до 9.

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

 

Команда «SED» устанавливает флаг десятичного режима (D) в регистре состояния процессора для включения режима BCD. Команда «CLD» очищает флаг D и возвращает 6510 к нормальной арифметической операции.

Когда включен режим BCD, флаг переноса действует по-разному для инструкций «ADC» и «SBC». Перенос распространяется от младшего полубайта к старшему, когда младший полубайт превышает 9, а затем от всего байта, когда он превышает 99, что позволяет правильно обрабатывать арифметические операции для значений отображения на экране.

Переключитесь на файл Arithmetic.asm.

В остальных примерах кода в этой главе нет загрузчика BASIC в начале и инструкции RTS в конце. Код также начинается в ячейке памяти 0 с использованием директивы «* = $ 0».

Это альтернативный способ тестирования кода, когда вам не нужно запускать в эмуляторе VICE (или на C64 / 128). В этом случае нет необходимости пропускать байты при отладке, а наличие кода, начинающегося с 0, упрощает вычисление количества используемых байтов памяти.

 

Arithmetic.asm

*=$0 ; For debugging only

;=================================================

 #region Main

         ; 8-bit addition
           CLC                                    ; Clear carry before add
           LDA #2                             ; Get first number
           ADC #$0A                       ; Add to second number

; 8-bit subtraction
           SEC                                    ; Set carry before subtract
           LDA #88                           ; Get first number
           SBC #%00000011         ; Subtract second number

           ; Shift & Rotate
           ASL                                    ; Arithmetic shift left
           ROL                                   ; Rotate left
           LSR                                    ; Logical shift right
           ROR                                  ; Rotate right

           ; Binary coded decimal
           SED                                   ; Set decimal mode
           CLC                                    ; Clear carry before add
           LDA #2                             ; Get first number
           ADC #$0A                       ; Add to second number
           CLD                                   ; Clear decimal mode

#endregion

• Выберите Debugger-> Debug Program (или F8), чтобы скомпилировать программу в машинный код и открыть инструмент отладчика.

• Выберите Debug-> Step Program, и флаг переноса (C) сбрасывается на 0, готовый к добавлению. Флаги регистра состояния процессора отображаются в отладчике как NV-BDIZC. В этом случае флаг переноса уже был равен 0.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 02. Постоянное значение 2 было скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 0C. Постоянное значение $ 0A (десятичное 10) было добавлено к значению, уже находящемуся в аккумуляторе, давая $ 0C. Флаг переноса (C) также был сброшен до 0, поскольку сумма не превышала 255.

 

Помните, что значения можно вводить в шестнадцатеричном (префикс $), десятичном (без префикса) или двоичном (префикс %) виде. Отладчик отображает все значения в шестнадцатеричном формате, а ассемблер преобразует все значения в двоичный код для запуска на микропроцессоре.

Использование разных баз счисления не имеет никакого значения для окончательной программы и является просто удобством.

ВАЖНО! Помните о различных системах счисления, используемых в программе.

Попробуйте изменить числовые базы, чтобы увидеть эффект в отладчике.

• Выберите Debug-> Step Program, и флаг переноса (C) будет установлен на 1, готовность к вычитанию.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 58. Постоянное значение 88 (десятичное) было скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 55. Постоянное значение% 00000011 (десятичное 3) и инверсия флага переноса (0) были вычтены из значения, уже находящегося в аккумуляторе. Флаг переноса (C) также был установлен в 1, поскольку вычитаемые значения не превышали вычитаемое из значения.

 

• Выберите Debug-> Step Program, и значение регистра AC изменится на AA. Двоичное значение% 01010101 ($ 55) было сдвинуто на 1 позицию влево, давая % 10101010 ($ AA). 0 был сдвинут в бит 0, а 0 из бита 7 был сдвинут во флаг переноса (C).

• Выберите Debug-> Step Program, и значение регистра AC изменится на 54. Двоичное значение % 10101010 ($ AA) было сдвинуто на 1 позицию влево, давая % 01010100 ($ 54). 0 из флага переноса (C) был сдвинут в бит 0, а 1 из бита 7 был сдвинут во флаг переноса (C).

 

 

• Выберите Debug-> Step Program, и значение регистра AC изменится на 2A. Двоичное значение % 01010100 ($ 54) было сдвинуто на 1 позицию вправо, давая % 00101010 ($ 2). 0 был сдвинут в бит 7, а 0 из бита 0 был сдвинут во флаг переноса (C).

• Выберите Debug-> Step Program, и значение регистра AC изменится на 15. Двоичное значение % 00101010 ($ 2A) было сдвинуто на 1 позицию вправо, давая% 00010101 ($ 15). 0 из флага переноса (C) был сдвинут в бит 7, а 0 из бита 7 был сдвинут во флаг переноса (C).



• Выберите Debug-> Step Program, и десятичный флаг (D) будет установлен на 1, готовность к двоично-десятичной (BCD) арифметике.

• Выберите Debug-> Step Program, и флаг переноса (C) сбрасывается на 0, готовый к добавлению.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 02. Постоянное значение 2 было скопировано в аккумулятор.

 


• Выберите Debug-> Step Program, и значение регистра AC изменится на 12. Постоянное значение $ 0A (десятичное 10) было добавлено к значению, уже находящемуся в аккумуляторе, давая $ 12. Флаг переноса (C) также был сброшен до 0, поскольку сумма не превышала 99. Обратите внимание, что сумма 2 + 10 теперь сохраняется как 12, а не как шестнадцатеричный 0C из более раннего сложения без BCD.

• Выберите Debug-> Step Program, и десятичный флаг (D) сбрасывается на 0 и готов к нормальной арифметической операции.


 

Логика

6510 имеет 3 инструкции, использующие поразрядную логику. Это «AND», «ORA» и «EOR». Каждая операция берет байт в сумматоре, поочередно проверяет каждый бит в сравнении с байтом в памяти и обновляет аккумулятор с результатами.

 

                                           AND

Пример: %10101010 ($AA) AND %11110000 ($F0) = %10100000 ($A0)


                                           ORA

Пример: %10101010 ($AA) ORA %11110000 ($F0) = %11111010 ($FA)


                                           EOR

Пример: %10101010 ($AA) EOR %11110000 ($F0) = %01011010 ($5A)

 

Логические инструкции особенно полезны для установки и очистки отдельных битов или диапазона битов в ячейках памяти, которые отображаются в аппаратные регистры.

Многие из 8-битных аппаратных регистров Commodore 64 выполняют несколько функций. Например, старшие 4 бита регистра могут выполнять одну функцию, а младшие 4 бита могут делать что-то совершенно другое.

Установите бит (ы): «ORA» со значением маски, содержащим 1 для бит (ов), который должен быть установлен.

Пример:         установить биты 6 и 0
                           Значение регистра   %00001111 ($0F) ORA
                           Маска                              %01000001 ($41) =
                                                                           %01001111 ($4F)

 

Очистить бит (ы): «AND» со значением маски, содержащим 0 для бит (ов), которые должны быть очищены.

Пример:         очистить биты 2 и 1
                           Значение регистра   %11100111 ($E7) AND
                           Маска                              %11111001 ($F9) =
                                                                           %11100001 ($E1)

 

Переключить бит (ы): «EOR» со значением маски, содержащим 1 для бит (ов), которые должны быть переключены.

Пример:         переключить биты 5 and 3
                           Значение регистра   %11110000 ($F0) EOR
                           Маска                              %00101000 ($28) =
                                                                           %11011000 ($D8)


Переключитесь на файл Logic.asm.

Logic.asm

#region Main

           ; Set bits
           LDA #%01010101         ; Load $55 into accumulator
           ORA #%11110000        ; Set highest 4 bits

           ; Clear bits
           LDA #%10001111         ; Load $8F into accumulator
           AND #%11110000        ; Clear lowest 4 bits

           ; Toggle bits
           LDA #%11111111         ; Load $FF into accumulator
           EOR #%10000001         ; Toggle bits 7 and 0

#endregion

 

• Выберите Debugger-> Debug Program (или F8), чтобы скомпилировать программу в машинный код и открыть инструмент отладчика.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 55. Постоянное значение %01010101 ($55) было скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC изменится на F5. Значение маски
%11110000 ($F0) использовалось для установки 4 старших бита в аккумуляторе, давая значение
%11110101 ($F5).

 

 

• Выберите Debug-> Step Program, и значение регистра AC изменится на 8F. Постоянное значение %10001111 ($8F) было скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 80. Значение маски
%11110000 ($F0) использовалось для очистки младших 4 бита в аккумуляторе, давая значение
%10000000 ($80).

 

 

• Выберите Debug-> Step Program, и значение регистра AC изменится на FF. Постоянное значение % 11111111 ($FF) было скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 7E. Значение маски
% 10000001 ($81) использовалось для переключения первого и последнего битов в аккумуляторе, давая значение % 01111110 ($7E).


 

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

 

Ветви и петли ( циклы )

Ветвь - это когда микропроцессор переключает поток выполнения программы на основе решения о состоянии. В языках программирования высокого уровня это представлено конструкцией if / else.

                           Разветвление


6510 имеет 8 инструкций для обработки ветвей. Каждая из них проверяет определенный бит в регистре состояния процессора и либо переходит к новому месту кода, либо переходит к следующей инструкции на основе определенного условия. Новое расположение кода устанавливается путем изменения регистра счетчика программ и может быть предоставлено либо с помощью метки, которую ассемблер должен преобразовать в адрес памяти, либо путем непосредственной подачи адреса памяти.

 

BCC   Branch on carry clear (C = 0)                   Разветвление при сбросе (C = 0)
BCS   Branch on carry set (C = 1)                     Переход по набору переноса (C = 1)
BNE   Branch on not equal to zero (Z = 0)    Ветвь не равна нулю (Z = 0)
BEQ   Branch on equal to zero (Z = 1)                            Ветвь равна нулю (Z = 1)
BPL    Branch on plus (N = 0)                             Ветвь на плюс (N = 0)
BMI   Branch on minus (N = 1)                         Ветвь на минусе (N = 1)
BVC   Branch on no overflow (V = 0)             Переход без переполнения (V = 0)
BVS   Branch on overflow (V = 1)                     Ответвление при переполнении (V = 1)


Инструкции перехода используют относительную адресацию памяти для операнда. Когда абсолютный адрес памяти (или метка) предоставляется ассемблеру, он преобразуется в байт, содержащий значение со знаком. Знаковое значение использует старший бит (бит 7) как положительное смещение (с 0) или отрицательное смещение (с 1).

Хотя ассемблер автоматически обрабатывает преобразование смещения, проблема заключается в том, что максимальное количество байтов, которое может перескочить инструкция ветвления, составляет +127 байтов вперед или -128 байтов назад.

Это ограничение ветвления можно преодолеть, изменив логику условного теста на обратную и используя инструкцию JPM, которая может использовать абсолютную адресацию памяти (продемонстрированная в примере кода для этого раздела).

ВНИМАНИЕ! Инструкции разветвления могут переходить только на +127 или -128 байт.


Цикл использует счетчик, а также проверку ветвления и условия таким образом, чтобы код можно было повторять до тех пор, пока условие не будет выполнено. В языках программирования высокого уровня это представлено циклами for и while.


6510 может использовать встроенные регистры X или Y как счетчики или любую ячейку памяти, и для этих счетчиков есть специальные инструкции увеличения и уменьшения.


INX / DEX        Увеличение / уменьшение регистра X
INY / DEY        Увеличение / уменьшение регистра Y
INC / DEC        Увеличение / уменьшение ячейки памяти


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


CPX   Сравнить с регистром X
CPY   Сравните с регистром Y
CMP Сравните с аккумулятором


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

                                                      N         Z          C
A, X, or Y < Memory                          1         0         0
A, X, or Y = Memory                          0         1         1
A, X, or Y > Memory                          0         0         1


Используя правильную комбинацию инструкции тестирования и инструкции перехода, можно получить любой требуемый логический тест, например: >, > =, ==, <=, <.

Пример: если бы мы использовали «INX» для увеличения регистра X на каждой итерации цикла, можно было бы использовать инструкцию «CPX» для проверки регистра X на конкретное значение и установки флагов регистра состояния процессора N, Z и C. Если мы затем воспользуемся инструкцией ветвления «BCC», она будет ветвиться (то есть зацикливаться) каждый раз, когда флаг C = 0. Он выйдет из цикла, когда C! = 0. Поэтому мы реализовали цикл, пока регистр меньше памяти (<).

Не всегда необходимо использовать тестовую инструкцию перед инструкцией сравнения в цикле, поскольку некоторые другие инструкции также обновляют регистр состояния процессора. Например, DEX установит флаг нуля (Z), когда регистр X достигнет 0, как и инструкция «LDX», если загруженное значение было 0. (См. главу инструкций 6510, чтобы узнать, какие инструкции обновляют флаги регистра состояния процессора.)

Переключитесь на файл Branches and Loops.asm.


Branches and Loops.asm

#region Main

           ; If/else (branch not taken)
           LDX #1            ; Load 1 into X register
           BEQ l1            ; Branch to l1 if Z = 1
           INX               ; Increment the X register
l1                                   ; Label l1

           ; If/else (branch taken)
           BNE l2              ; Branch to l2 if Z = 0
           INY                    ; Increment the Y register
l2                                        ; Label l2

           ; Loop (increasing counter)
           LDY #0              ; Load 0 into Y register
l3                                        ; Label l3

; repeat 124                    ; too many bytes for a
; nop                                  ; branch instruction to
; endrepeat                     ; jump over

           INY                    ; Increment the Y register
           CPY #2             ; Compare Y & 2, set NZC flags
           BCC l3               ; Branch to l3 if C = 0

; BCS l5                              ; Branch to l5 if C != 0
; JMP l3                             ; Jump to l3
; l5

#endregion

 

• Выберите Debugger-> Debug Program (или F8), чтобы скомпилировать программу в машинный код и открыть инструмент отладчика.

• Выберите Debug-> Step Program, и значение регистра X изменится на 01. Постоянное значение 1 было скопировано в регистр X. Флаг Z также был сброшен на 0 (т.е. скопированное значение не было нулевым).

 

 

• Выберите Debug-> Step Program, и выполнение программы перейдет к следующей инструкции. Инструкция «BEQ» проверяет нулевой флаг (Z), и, поскольку он был равен 0 (т.е. не установлен), переход был проигнорирован.

• Выберите Debug-> Step Program, и значение регистра X изменится на 02. Инструкция «INX» предназначена только для демонстрации того, что выполнение программы продолжается на следующей инструкции, если ветвление не выполнено.

 

 

• Выберите Debug-> Step Program, и выполнение программы пропускает следующую инструкцию «INY» и переходит к инструкции после метки «l2». Инструкция «BNE» проверяет нулевой флаг (Z), и, поскольку он был равен 0 (т.е. не установлен), переход был выполнен.

Обратите внимание, что машинный код для инструкции «BNE l2» - «D0 01». D0 - это код операции «BNE», а 01 было преобразовано ассемблером из адреса памяти метки «l2» в прямое смещение в 1 байт. т.е. если ветвь взята, пропустить 1 байт.


 

• Выберите Debug-> Step Program, и значение регистра Y останется равным 00. Регистр Y был сброшен на ноль для использования в качестве счетчика цикла. В этом случае сброс не нужен, но всегда можно сбросить счетчик.

• Выберите Debug-> Step Program, и значение регистра Y изменится на 01. Команда «INY» использовалась для увеличения регистра Y на 1. Она используется для увеличения счетчика цикла на каждой итерации.



• Выберите Debug-> Step Program, и флаг N установлен на 1, флаг Z на 0 и флаг C на 0. Команда «CPY» сравнила значение регистра Y (1) с постоянным значением 2. Поскольку Y < Постоянного значения (или константа имеет значение 2 в данном случае), значения 1, 0, 0 из предыдущей таблицы использовались для установки флагов состояния процессора NZC.

• Выберите Debug-> Step Program, и выполнение программы вернется к метке «l3». Инструкция «BCC» проверила флаг переноса (C), и, поскольку он был равен 0 (то есть не установлен), ветвление было выполнено.



• Выберите Debug-> Step Program, и значение регистра Y изменится на 02. Счетчик цикла был увеличен на 1 (аналогично ++ или + = 1 в языке высокого уровня).

• Выберите Debug-> Step Program, и флаг N установлен на 0, флаг Z на 1 и флаг C на 1. На этот раз значение регистра и память (или константа) были равны.

• Выберите Debug-> Step Program, и выполнение программы продолжится. Команда «BCC» проверяет флаг переноса (C) и, поскольку он равен 1 (т.е. установлен), ветвление не было предпринято, поэтому цикл был завершен.


 

• Выйдите из инструмента отладчика и снимите комментарии со строк из данного кода «repeat», «nop» и «endrepeat».


Branches and Loops.asm

           . . .

           repeat 124     ; too many bytes for a
           nop                   ; branch instruction to
           endrepeat     ; jump over

           . . .

 

Это вставляет в цикл 124 инструкции «nop» (без операции). Эти инструкции ничего не делают, кроме использования процессорного времени, и обычно используются для точного определения времени. Здесь мы используем их, чтобы продемонстрировать ограничение с помощью инструкций перехода.

• Выберите Debugger-> Debug Program (или F8), чтобы попытаться скомпилировать программу в машинный код и открыть инструмент отладчика.

Ассемблер не может построить программу и выводит следующее сообщение об ошибке.

 


Это связано с тем, что теперь значение для инструкции перехода больше, чем +127 или -128 байтов.

Чтобы исправить ошибку, закомментируйте инструкцию «BCC» и добавьте комментарий в «BCS», «JMP» и метку «l5».

 

Branches and Loops.asm

           . . .

                           ; BCC l3            ; Branch to l3 if C = 0

                           BCS l5               ; Branch to l5 if C != 0
                           JMP l3              ; Jump to l3
          
l5

           . . .

 

Теперь это меняет логику ветвления на противоположную, поэтому цикл всегда повторяется, если C! = 0, и в этом случае он перейдет к метке «l5» и выйдет из цикла. «BCS» теперь имеет только небольшое расстояние для прыжка, а инструкция «JMP» не имеет этого ограничения, поэтому она работает для прыжков на большее расстояние. Теперь код собирается и отлаживается как обычно.

Все микропроцессоры запускают свою собственную версию машинного кода и, следовательно, не выполняют инструкции языка высокого уровня изначально. Так, например, языковой цикл «C» компилируется в отдельные инструкции машинного кода "под капотом", аналогичным представленному здесь.

Попробуйте реализовать цикл с уменьшающимся счетчиком.

 

Макросы и подпрограммы

Описания макросов и подпрограмм в этом разделе относятся к языку ассемблера 6502 и, в частности, к среде CBM prg Studio. Определения и использование могут несколько отличаться для других языков и сред программирования.

Макросы - это блоки кода, которые определены один раз для многократного использования. Каждый раз, когда требуется запустить код макроса, имя макроса вставляется в код. Ассемблер заменяет все вхождения имени макроса копией кода макроса.

Подпрограммы также представляют собой блоки кода, которые определены один раз для многократного использования, но сохраняется только одна копия кода подпрограммы. Каждый раз, когда требуется запустить код подпрограммы, в код вставляется инструкция «JSR» (переход к подпрограмме), за которой следует имя подпрограммы. Инструкция «RTS» (возврат из подпрограммы) вставляется в конец кода подпрограммы. Выполнение кода переходит от «JSR» к подпрограмме, а затем от «RTS» обратно к точке после вызова подпрограммы.

Поэтому подпрограммы занимают меньше памяти, чем макросы (особенно если вызываются несколько раз), но используют на 2 инструкции больше за вызов, поэтому их выполнение будет медленнее.

 

 

Макросы также могут передавать параметры, чего не могут подпрограммы. Эти параметры могут быть значениями или адресами памяти и помечаются в конце вызова макроса.

 

                                           Пример вызова макроса

 

Суффиксы _V и _A показывают количество и тип параметров (1st - это значение, а 2nd - адрес в этом примере), и это соглашение, выбранное для ясности кода.

Код макроса выбирает параметр для использования с / 1 для 1-го, / 2 для 2-го, / 3 для 3-го и т. д.

Префикс «#» указывает на прямое использование значения, в противном случае оно принимается за адрес памяти.

 

Пример кода макроса

defm TESTMACRO_VA

           LDA #/1                           ; Load value from param 1 (# used)
           LDX /2              ; Load value from param2 address

endm

 

Метки внутри макроса могут вызывать конфликты имен, когда код копируется ассемблером несколько раз. Добавление символа «@» перед именами меток макросов идентифицирует их как локальные и устраняет проблему.

Чтобы получить преимущества экономии пространства кода, предоставляемого подпрограммами, с возможностью передачи параметров макросов, макрос может вызывать подпрограмму, используя временные переменные для хранения параметров (показано в примере кода для этого раздела).

Переключитесь на файл Macros and Subroutines.asm.

 

Macros and Subroutines.asm

#region Main

TESTMACRO_VA 3, myVariable
TESTMACRO_CALLING_SUBROUTINE_VA 8, myVariable

#endregion

;=================================================

#region Macros and Subroutines

defm TESTMACRO_VA

           LDA #/1                                           ; Load value from param 1 (# used)
           LDX /2                              ; Load value from param2 address

endm

defm TESTMACRO_CALLING_SUBROUTINE_VA

           LDA #/1                                           ; Load value from param 1 (# used)
           STA /2                              ; Store value into param2 address

           JSR testSubroutine     ; call the subroutine

endm

testSubroutine

           LDA myVariable                           ; Load value from variable
           RTS                                    ; Return from subroutine

#endregion

;=================================================

#region Variables

; 1 byte reserved and defaulted to 5
myVariable byte 5

#endregion

 

• Выберите Debugger-> Debug Program (или F8), чтобы скомпилировать программу в машинный код и открыть инструмент отладчика.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 03. Постоянное значение 3 было передано как 1-й параметр и скопировано в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра X изменится на 05. Адрес памяти $ 0E (myVariable) был передан в качестве 2-го параметра, а значение 5 из этого адреса было скопировано в регистр X.

 

 

• Выберите Debug-> Step Program, и постоянное значение 8 передается как 1-й параметр и копируется в аккумулятор.

• Выберите Debug-> Step Program, и значение регистра AC 8 будет скопировано в адрес памяти $0E (myVariable), который был передан как 2-й параметр.

• Выберите Debug-> Step Program, чтобы запустить подпрограмму.

• Выберите Debug-> Step Program, и значение регистра AC изменится на 08, которое было передано через переменную в код подпрограммы.


 

 


Поделиться с друзьями:

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.173 с.