Pull to refresh

Немного логики…

Reading time2 min
Views2.4K
image

Задача #2 «Позитивные автоматы»



Для тех, кто не хочет читать:

Найти значение выражения: |x — |y||
X, Y — любые целые ( и отрицательные тоже )

Ограничение: нельзя пользоваться sub, dec… и любое другое вычитание, нельзя пользоваться регистрами флагов и бинарными операциями. (в частности сдвигами)
Все что у вас есть: je, cmp (нельзя смотреть флаги), jmp, inc, mov. (я же сказал, немного)

Для того, что бы лучше разобраться в задаче:

Есть такая замечательная штуковина, называется:
Машина с неограниченными регистрами (МНР)
Итак, зачем это? Лично для меня — расшевелить мозги.

Теперь попробуем в деле!


Как ей можно пользоваться? Пример: сложите два числа, в R0-первое число, в R1-второе число. Ответ записать в R0, при том r0, r1 >= 0

Замечание: я пишу имена регистров rn, а не Rn, и имена команд тоже маленькими, имхо удобнее.

Решение:
с1) s(r0); x = x+1
c2) s(r2); r2 = r2+1
c3) j(r2,r1,c1); если r2=r1, тогда прыгнуть на с1.
с4)

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

Вольности:
— давать меткам любые имена (то что перед скобкой)
— можно писать пустые метки (что бы ссылаться на них и выходить из программы.)
— делать прыжки типа J(1,1,), это эквивалент безусловного прыжка
— делать записи типа T(, ), например: T ( r1, 5) (вообще этого нельзя делать, но ....)
— комментраии после ";", но вы как хотите уж

Ограничения:
— прыгать можно только на метки (нельзя делать адрес переменным)
— класть в регистры отрицательные числа

Если на МНР писать большие программы (например ОС), удобно сделать эквивалентные команды для ассемблера (тестирование).

Заметка:
r0.....rn — это зарезервированные в памяти слова. Пример: r0 dw 0
При том все «регистры» сначала в нуле.

МНР команды / АСМ. эквивалент

T(r1,r2) <=> mov ax,r2
mov r1,ax

S(r1) <=> inc r1

Z(r1) <=> mov r1,0

J(r1,r2,c1) <=> mov ax,r2
cmp r1,ax
je c1

J(1,1,c1) <=> jmp c1

В общем идея: завязать себе правую руку на ноге, склеить 3 пальца на левой руке и пойти прогить на асме. Ну ничего, у нас целые 4 команды.


Хватит теории, пора задачи решать.

Задача 1. Найти ошибку в моем примере.
Задача 2. Вычесть одно число из другого, при том первое больше. r0 — первое, r1- второе. Результат в r0
Задача 3. Найти значение выражения: |x — |y||
X, Y — любые целые ( и отрицательные тоже )
r0 — x; r1-y. Результат записать в r0. В комментариях привести аналог на ассемблере или на МНР.

P.S. все это я написал, надеясь, что у вас тоже появятся интересные задачи, с такими же ограничениями.
P.P.S. В комментариях находится решение Ayay на МНР, после этого мое, на ASM.
P.P.P.S. я сознательно расширил возможности МНР. По определению, она (МНР) вообще работает только с натуральными числами; я ввел пересылку в T(rn,), т.е. это пересылка числа в регистр сразу. До этого можно было только из регистра в регистр, но нельзя пересылать отрицательные числа.
Tags:
Hubs:
Total votes 20: ↑16 and ↓4+12
Comments41

Articles