Написание цикла while в сборке - PullRequest
9 голосов
/ 16 мая 2011

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

Два кода, которые я считаю полезными:

  1. Сравнение байта в памяти с X reg (сокращение: CPX, hex: EC). Это устанавливает Z флаг на ноль, если он равен и
  2. Ветвь X байтов, если Z flag = 0 (сокращение: BNE, hex: D0)

Ответы [ 4 ]

6 голосов
/ 16 мая 2011

Вот место для начала: http://www.obelisk.demon.co.uk/6502/. На странице представлен кросс-ассемблер, который вы можете запустить на своем ПК. Это может быть хорошей платформой для вас.

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

- подготовка «исходного файла», так называемого, символических инструкций, которые вы назвать "стенографию"
- используя ассемблер, переводя этот источник подать в машинные инструкции, которые 6502 понимает
- загрузка перевод в 6502
- рассказывать 6502 выполнить переведенный машинные инструкции

Ваша программа-пример пытается скопировать LEN байтов памяти из SRC в DST.

Вы форматируете это так:

      LDX #0    ; Start with the first byte 
_LOOP LDA SRC,X ; load a byte from SRC into the A register 
      STA DST,X ; store that byte into DST
      INX       ; bump the index register to point to the next SRC and DST locations 
      CPX #LEN  ; have we moved LEN characters?  
      BNE _LOOP ; if not, go move the next one

После того, как вы добавили больше строк выписки (например, END); и после того, как вы определили SRC, DST и LEN, вы сохраняете все это в файле, скажем, cploop.txt.

Тогда вы говорите ассемблеру перевести это. Ассемблер выпускает файл двоичного машинного кода 6502, который можно представить в виде шестнадцатеричных байтов, о которых вы говорите.

Вы передаете этот файл машинного кода на имитированный 6502. Затем вы как-то просите 6502 выполнить операции, которые воплощает машинный код.

3 голосов
/ 12 июня 2014

Вот пример, показывающий соответствие между сборкой (то, что вы называете «сокращением») и машинным кодом. Во-первых, вот код ассемблера для алгоритма с некоторыми абстрагированными параметрами:

* = 4000          ; This is the address where our program will be stored

      LDX #len
loop  LDA src,X 
      STA dest,X 
      DEX       
      BNE loop

Конечно, вы не можете превратить это непосредственно в машинный код. Вам также необходимо заполнить значения len, src и dest:

src = $1234
dest = $5678
len = 10

В имени loop нужно понимать, что точно так же, как src присваивается значение $1234, loop будет присвоен адрес инструкции после него. Таким образом, в этом случае, поскольку LDX #len занимает 2 байта (как я скоро вам покажу), loop устанавливается в $4000 + 2 = $4002. Это выполняется автоматически ассемблером, но, конечно, вы можете сделать все это и на бумаге.

Так, каков машинный код 6502 для вышеупомянутой программы сборки?

A2 0A
BD 34 12
9D 78 56
CA
D0 F7

Откуда мне это знать? Ну, я только что вставил вышеупомянутую программу в онлайн-ассемблер 6502 по адресу http://www.masswerk.at/6502/assembler.html. Она даже показывает вам детальное сопоставление между сборкой и машинным кодом:

4000        LDX #LEN        A2 0A
4002 LOOP   LDA SRC,X       BD 34 12
4005        STA DEST,X      9D 78 56
4008        DEX             CA
4009        BNE LOOP        D0 F7
400B

Обратите внимание, что фактическое значение LOOP даже не используется для вычисления машинного кода для BNE LOOP, только его относительный адрес по сравнению с самой инструкцией BNE: F7 равно -9, и разница между $400B и $4002 - это -9!

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

2 голосов
/ 18 августа 2013

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

Примеры:
$D0 $00: no-op: ветвь переходит к следующей инструкции независимо от условия
$D0 $FE: ветвь указывает на себя, создавая бесконечный цикл, если Z=0.

1 голос
/ 18 августа 2013

A while утверждение действительно означает:

  1. проверить условие
  2. если условие ложно, перейти к 5
  3. сделать что-то
  4. вернуться к 1 (простой JMP или ветвь)
  5. остальная часть программы

С 6502 все это не будет чрезвычайно простым, если вы не можете сделать многопредположения.Если условие, которое вы тестируете, всегда будет регистром, инструкции сравнения (cmp, cpx, cpy) и ветвления, очевидно, то, что вам нужно для 1.

Если это будет храниться один байтв памяти, затем вам нужно загрузить этот байт, а затем сравнить его.

Если это 16-битное значение, хранящееся в двух байтах, вам необходимо загрузить и протестировать каждое значение байта.

Работа с поплавками?Если вы написали или имеете доступ к пакету с плавающей запятой (например, подпрограммам с плавающей запятой Commodore 64 ROM BASIC), вам нужно будет их использовать.

Вы можете понять, почему языки высокого уровня содержат данныетипов.

Так что, на самом деле, это зависит от типа данных, с которыми вы имеете дело, но любая реализация while в 6502 должна в значительной степени следовать вышеприведенному.в вашем вопросе все в порядке, если вы знаете, что сравниваемые данные всегда будут в X, и что ваш пункт назначения всегда будет на расстоянии + 127 / -128 байт (предел диапазона команд Bxx).

...