Здесь вы сможете найти как минимум 3 способа, как сломать команду loop
. Наслаждайтесь =)
Когда мы используем прямую загрузку операнда в LOOP:
loop #75
Каждый раз будет загружаться одно и то же значение, оно же будет уменьшаться и далее передаваться управление в зависимости от предоставленного значения.
Таком образом для любого положительного числа (например, 0x75
) предоставленного прямой загрузкой, loop всегда будет передавать управление следующей команде, поскольку в ячейке памяти всегда будет положительное число (логично)
Если значение отрицательное (e.g. 0xF5
) команда будет вести себя, будто в памяти отрицательное число, то есть, всегда перепрыгнет через 1 команду.
(Положительное значение) Перед исполнением:
-> 8F75
0700
0100
После:
0074
-> 0700
0100
(Отрицательное значение) Перед исполнением:
-> 8FF5
0700
0100
После исполнения:
FFF5 ; знак был расширен, именно поэтому вы видите FFF5 вместо 00F5
0700
-> 0100
Note: остальные режимы адресации должны корректно работать с этой командой
Этот режим адресации не ломает команду loop
если она используется так, как показано ниже:
org 0x10
word 0x5 ; <- операнд
POINTER: word 0x10 ; <- адрес
loop (POINTER)+ ; <- автоинкрементная адресация
inc
hlt
-
Увеличивает адрес на 1 и помещает его в
Data Register
-
Сохраняет содержимое
Data Register
(т.е. увеличенный адрес) вPOINTER
(0x10 -> 0x11
) -
Уменьшает адрес хранимый сейчас в
Data Register
(далееDR
) обратно на 1 (0x11 -> 0x10
). Учтите, чтоDR
не был очищен после инкрементирования адреса, поэтому этот адрес остается в регистре. -
loop
уменьшает операнд0x5
(находится по адресу, сохраненному вDR
т.е.0x10
). (0x5
->0x4
)
Вечного цикла НЕ произойдет поскольку loop
выполняет уменьшение операнда а НЕ адреса.
Но стойте! Что... Что если адрес и операнд станут одни и те же. Итак... Мы получим следующее:
org 0x10
POINTER: word 0x10 ; notice pointer points to itself
LP: loop (POINTER)+
jump LP
hlt
Пожалуйста! Не запускайте это так как это разрушит вселенную до непоправимого состояния!
Таким образом происходит зацикливание команды loop.
0x10 -> 0x11 -> 0x10
и так далее.
Обратите внимание что сначала произойдет инкрементирование, поскольку инкрементирование адреса является частью цикла выборки адреса. В свою очередь, декремент операнда происходит во время цикла исполнения. Цикл выборки адреса предшествует Циклу исполнения.
Если значение в ячейке памяти эквивалентно 0x8000
или 0x8001
то команда НЕ совершит прыжок! Из-за особенностей проверок в команде loop
внутри команды произойдет переполнение с данными значениями.