Игры настоящих кодеров Shen (_shen_@mail.ru) Спецвыпуск Xakep, номер #035, стр. 035-054-3 Итак, следующая команда Redcode. «JMP A» передает управление на команду с адресом A (как ты помнишь, адресация идет относительно текущей команды). Так что затруднений с другим классическим воином – Wait, у тебя возникнуть не должно. Сохрани следующую строчку в файле wait.red: JMP 0 Да! Он ничего не делает, а просто каждый цикл передает управление на себя же, т.е. находится в бесконечном цикле. Вот с этим-то «воином» мы и стравим нашего Импа. File->Load, выбирай Импа и Вэйта, жми Run. Вопрос на засыпку: кто победит? А вот и нет! Не победит никто - pMARS объявит ничью! Почему? Помнишь, я давал два основных правила CoreWar? Я говорил, что программа проигрывает, только если попытается выполнить данные, а не код? То-то же. Имп, дойдя до того места, где стоит зацикленный Вэйт, перепишет его «JMP 0» своим «MOV 0, 1», и Вэйт сам превратится в Импа! То есть на поле боя будет два Импа, что, как мы уже говорили, приведет к ничьей! Получается, Имп вообще не способен победить кого-либо? В принципе, да – Имп может выиграть только в том случае, если вражеская программа самоуничтожится. Впрочем, как и Вэйт. Тем не менее, идея, положенная в основу Импа, используется во многих эффективных программах-бойцах. Тебе, наверное, уже не терпится посмотреть на полноценную программу, которая сможет победить хотя бы Вэйта? Мы напишем такую программу, но для этого нам нужно узнать еще две команды и познакомиться с другими способами адресации. ADD, DAT, @ и # «ADD A, B» прибавит команду с адресом A к команде с адресом B и запишет результат по адресу B. Такая форма ADD нас не устраивает, поэтому перепишем ее так: «ADD #A, B». Теперь это означает: прибавить число A ко второму операнду команды с адресом B (чаще говорят «к B-полю команды с адресом B»). Слишком запутанно? Смотри: ADD #1, 1 ; <--- MOV 0, 0 Команда ADD в данном примере прибавит число один к B-полю инструкции MOV, превратив эту команду в Импа: «MOV 0, 1». Т.е. знак # означает, что имеется в виду не адрес, а конкретное число. Что делает команда MOV в следующей программе? MOV 0, @1 ; <--- ADD #1, 1 Она копирует саму себя по адресу, на который указывает второй операнд команды по адресу 1. Ты помнишь, что все адреса рассчитываются относительно текущей инструкции? По адресу 1 находится команда ADD, второй операнд которой равен 1. Следовательно, MOV копирует саму себя по адресу, равному единице относительно ADD. Таким образом, после выполнения первой инструкции, поле будет выглядеть так: MOV 0, @1 ADD #1, 1 ; <--- MOV 0, @1 Понятно? Теперь разберемся поподробнее, как погибает процесс. Хочешь посмотреть на программу, которая проигрывает бой с Вэйтом? Смотри: |