Рискованный процессор Отрицание реестра

Мы рассматриваем процессор RISC, который имеет только несколько команд, таких как DBNZ. Я пытаюсь написать код, который записывает отрицание регистра A в B, а также второй отдельный код, который должен вычесть A из B и поместить результат в C

Я не уверен, как это сделать, я не знаю, может быть, это может быть возможно с Nasm Assembler, но это две разные вещи, но не знаю, как начать

1 ответ

Для записи, реальные архитектуры RISC (например, ARM или MIPS) богаче, чем DBNZ. То, что вы представляете, обычно обозначается как OISC или URISC.

Кстати, NASM не поможет. Он предназначен только для реальных процессоров; Ваша академическая модель. Но собрать эмулятор на языке высокого уровня было бы довольно тривиально. Я, вероятно, могу написать один на JavaScript через час или около того.

Синтаксис, который я предполагаю для его единственной команды:

DBNZ reg[, label]

и смысл такой:

reg = reg - 1
if label is given and reg != 0 then goto label

Если метка опущена, неявная цель перехода - это просто следующая инструкция. Для меня это кусочек синтаксического сахара для лучшей читаемости кода.

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


Алгоритм отрицания достаточно прост:

b=0
while a > 0
    a = a-1
    b = b-1

В сборке условный переход и декремент - это одно и то же. Так бы и получилось так:

;Zero out B
BZeroLoop:
DBNZ B, BZeroLoop ; Decrement until it's zero

;Main loop: subtract from A until it's zero, decrementing B on every iteration
NegLoop:
DBNZ B ; Decrement B with no jump
DBNZ A, NegLoop

Теперь вычитание. Алгоритм вычитания B из A на месте (т.е. результат остается в регистре A):

while b != 0
    b = b-1
    a = a-1

Фактически это тот же цикл, что и в отрицании, но без начального обнуления. Вы можете думать об отрицании как о случае вычитания на месте - в частности, это вычитание из нуля.

Но нам нужен результат, чтобы перейти к ц. На более низком уровне, мы бы просто назначить. Но у нас нет назначения. Возможно сделать назначение с двумя отрицаниями и временным регистром. Но мы можем обойтись одним отрицанием - сначала вычислим ba на месте, а затем сведем его к c:

while a != 0
    a = a-1
    b = b-1 ;this reduces b to the value of b-a

c = 0 ; also a loop

while b != 0
    b = b-1
    c = c-1

Или в сборке:

SubLoop: ; B = B-A
DBNZ B
DBNZ A, SubLoop

CZeroLoop: ; C = 0
DBNZ C, CZeroLoop

NegLoop: ; C = C-B
DBNZ C
DBNZ B, NegLoop
Другие вопросы по тегам