Язык ассемблера для чайников

Программирование на Ассемблере для начинающих с примерами программ

Многие считают, что Assembler – уже устаревший и нигде не используемый язык, однако в основном это молодые люди, которые не занимаются профессионально системным программированием. Разработка ПО, конечно, хорошо, но в отличие от высокоуровневых языков программирования, Ассемблер научит глубоко понимать работу компьютера, оптимизировать работку с аппаратными ресурсами, а также программировать любую технику, тем самым развиваясь в направлении машинного обучения. Для понимания этого древнего ЯП, для начала стоит попрактиковаться с простыми программами, которые лучше всего объясняют функционал Ассемблера.

IDE для Assembler

Первый вопрос: в какой среде разработки программировать на Ассемблере? Ответ однозначный – MASM32. Это стандартная программа, которую используют для данного ЯП. Скачать её можно на официальном сайте masm32.com в виде архива, который нужно будет распаковать и после запустить инсталлятор install.exe. Как альтернативу можно использовать FASM, однако для него код будет значительно отличаться.

Перед работой главное не забыть дописать в системную переменную PATH строчку:

Программа «Hello world» на ассемблере

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

Для начала запускаем редактор qeditor.exe в папке с установленной MASM32, и в нём пишем код программы. После сохраняем его в виде файла с расширением «.asm», и билдим программу с помощью пункта меню «Project» → «Build all». Если в коде нет ошибок, программа успешно скомпилируется, и на выходе мы получим готовый exe-файл, который покажет окно Windows с надписью «Hello world».

Сложение двух чисел на assembler

В этом случае мы смотрим, равна ли сумма чисел нулю, или же нет. Если да, то на экране появляется соответствующее сообщение об этом, и, если же нет – появляется иное уведомление.

Здесь мы используем так называемые метки и специальные команды с их использованием (jz, jmp, test). Разберём подробнее:

Программа суммы чисел на ассемблере

Примитивная программа, которая показывает процесс суммирования двух переменных:

В Ассемблере для того, чтобы вычислить сумму, потребуется провести немало действий, потому как язык программирования работает напрямую с системной памятью. Здесь мы по большей частью манипулируем ресурсами, и самостоятельно указываем, сколько выделить под переменную, в каком виде воспринимать числа, и куда их девать.

Получение значения из командной строки на ассемблере

Одно из важных основных действий в программировании – это получить данные из консоли для их дальнейшей обработки. В данном случае мы их получаем из командной строки и выводим в окне Windows:

Также можно воспользоваться альтернативным методом:

Здесь используется invoke – специальный макрос, с помощью которого упрощается код программы. Во время компиляции макрос-команды преобразовываются в команды Ассемблера. Так или иначе, мы пользуемся стеком – примитивным способом хранения данных, но в тоже время очень удобным. По соглашению stdcall, во всех WinAPI-функциях переменные передаются через стек, только в обратном порядке, и помещаются в соответствующий регистр eax.

Циклы в ассемблере

Для создания цикла используется команда repeat. Далее с помощью inc увеличивается значение переменной на 1, независимо от того, находится она в оперативной памяти, или же в самом процессоре. Для того, чтобы прервать работу цикла, используется директива «.BREAK». Она может как останавливать цикл, так и продолжать его действие после «паузы». Также можно прервать выполнение кода программы и проверить условие repeat и while с помощью директивы «.CONTINUE».

Сумма элементов массива на assembler

Здесь мы суммируем значения переменных в массиве, используя цикл «for»:

С помощью команды jne выполняется переход по метке, основываясь на результате сравнения переменных. Если он отрицательный – происходит переход, а если операнды не равняются друг другу, переход не осуществляется.

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

Источник

Ассемблер для чайников (Z80)

Основы

Это краткое описание, целью которого является понимание основ.

Регистры

Важно понять, что такое регистр, прежде чем идти дальше.

Регистры нельзя рассматривать как общую память, поскольку не все команды Z80 могут принимать все регистры в качестве параметров. Каждая пара регистров в любом случае имеет свои особенности того, для чего они хороши. Здесь я не пытаюсь описать все, что вы можете с ними сделать, поскольку есть руководства для этого, разве только некоторые типичные характеристики.

Наиболее важные пары регистров, которые нужно знать:

А и F, образующие регистровую пару AF. A также называется аккумулятором в некоторых документах. Этот регистр является наиболее важным регистром, поскольку все 8-битные вычисления выполняются для этого регистра. По этой же причине его практически невозможно использовать для хранения информации, поскольку в результате вы очень часто загружаете и сохраняете этот регистр. F также очень важный регистр, но его нельзя использовать напрямую. Он делится на отдельные биты состояния, называемые флагами, которые меняются каждый раз, когда ЦП выполняет команду, которая должна вернуть статус. Отдельные биты этого регистра имеют разные имена, такие как флаг переноса (C), флаг нуля (Z) и так далее. Пожалуйста, прочтите про флаги ниже, для получения дополнительной информации. AF в качестве пары регистров не может использоваться вместе, кроме как для сохранения аккумулятора вместе с флагами состояния в памяти или его восстановления.

B и C, образующие регистровую пару BC. Эти регистры можно использовать как временное внутреннее хранилище ЦП. Обычно это хороший выбор в качестве 8-битного счетчика цикла. Используется, когда вам нужно указать порт ввода / вывода. Вместе регистровая пара BC обычно используется для хранения 16-битной «длины» или другого 16-битного значения, необходимого для расчета.

H и L, образующие регистровую пару HL. Как отдельные регистры, они также не имеют никаких «особых даров», но, когда они используются вместе, они образуют наиболее важную 16-битную пару, как правило, все 16-битные вычисления выполняются с HL. Он часто используется также как «источник» при наведении памяти.

Пара SP. Это 16-битный указатель, который определяет, где такие команды, как CALL или PUSH, хранят свою информацию. Начинающему программисту очень редко приходится напрямую манипулировать этим регистром, но это полезно знать. Также важно знать, что это указывает на конец хранилища, поэтому любые новые значения сохраняются до адреса, на который он указывает, и содержимое SP уменьшается на 2. 8-битные значения, которые образуют пару регистров, никогда не используются по отдельности, поэтому у них даже нет 8-битных имен.

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

Остальные регистры:

Пара PC, также известный как счетчик программ (Program Counter). Это всегда указывает на то, откуда Z80 читает программу, и, хотя это очень важно, программисту очень редко приходится думать об этом как о паре регистров. 8-битные значения, которые образуют пару регистров, никогда не используются по отдельности, поэтому у них даже нет 8-битных имен. PC также никогда не указывается напрямую, но им манипулируют с помощью команд, таких как JP xxxx (прыжок), которые можно представить как LD PC, xxxx или RET, которые можно представить как POP PC.

IXh и IXl, которые образуют регистровую пару IX. Как отдельные регистры они довольно хороши как временное хранилище. Они медленнее, чем ранее упомянутые альтернативы, но все же быстрее, чем использование внешней оперативной памяти ЦП. Использование их в качестве отдельных регистров в любом случае официально не документировано. Практически они безопасны в использовании, но вы можете найти ассемблер, который не компилирует код, если вы используете такие имена, как IXl или IXh. Как пара они ведут себя очень похоже на HL, только медленнее. Особенностью является то, что во многих случаях вы можете использовать дополнительное значение смещения, когда вы используете IX в качестве указателя.

IYh и IYl, которые образуют пару регистров IY. Эти регистры работают как индивидуально, так и в паре. Во всех случаях работают точно так же, как IX.

I и R, которые образуют регистр пары IR. Это очень специфические регистры, которые редко имеют какое-либо практическое применение. I связан с обработкой прерываний, но имеет очень мало случаев использования в среде MSX. Часть R используется как внутренний счетчик Z80, который иногда используется как источник случайного начального числа. Они более новые, используемые в качестве пары регистров, хотя в некоторых документах может появляться IR.

BC ‘, DE’, HL ‘и AF’. Они называются «теневыми регистрами» и представляют собой просто альтернативные внутренние хранилища для пар регистров BC, DE, HL и AF. Вы можете поменять место хранения с помощью команд EXX и EX AF, AF ‘, но это все, что вы можете сделать.

Флаги

Как правило, все, что связано с вычислением чего-либо, влияет и на флаги. 16-битные команды INC и DEC являются исключением из этого правила. Обычно на флаги НЕ влияют команды перехода, команды управления ЦП или прерывания или инструкции загрузки. Загрузка из регистра I или R является исключением из этого второго правила.

Вот список флагов в F-регистре:

бит 7, SF, знак флага. Это копия результатов наиболее значимого бита. Если бит установлен (= 1 = «M») «Minus», значение из 2-х дополнений является отрицательным, в противном случае результат будет положительным (= 0 = «P») «Plus». Обратите внимание, что этот флаг можно использовать только с условной инструкцией JP.

бит 6, ZF, нулевой флаг. Если результат математической операции равен нулю, бит устанавливается (= 1 = «Z»), другими словами, бит сбрасывается (= 0 = «NZ») «Not zero»

Бит 5, YF, копия результатов 5-го бита.

Бит 4, HF, «Half-carry» от бита 3 до 4. Z80 использует это внутренне для коррекции BCD.

Бит 3, XF, копия результатов, 3-й бит.

Бит 2, PF / VF, флаг четности. Это копия младшего значащего бита результатов. Если бит установлен (= 1 = «PO»), четность нечетна, в противном случае результат будет четным. (= 0 = «PE») в некоторых случаях этот бит может использоваться для указания переполнения со знаком с 2 комплиментами. (VF) Обратите внимание, что этот флаг может использоваться только с условной инструкцией JP.

Бит 1, NF, этот бит используется внутренним Z80 для указания, была ли последняя операция сложением или вычитанием (необходимо для коррекции BCD)

В дополнение к этим флагам есть еще два внутренних флага Z80, о которых пользователь редко должен знать, но они указаны для полноты:

IFF1 используется внутри Z80, чтобы указать, есть ли ожидающее прерывание
IFF2, это резервная копия IFF1, так что состояние может быть восстановлено.

Вы также можете сохранить или извлечь адрес в стек с помощью PUSH и POP, но будьте осторожны, чтобы не помешать выполнению программы.
Будьте осторожны, чтобы не перезаписать данные или подпрограмму из-за чрезмерного сохранения адресов.

Заявления для кодов операций

Есть несколько типов утверждений, которые мы можем классифицировать на девять групп.

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

Обычно в ассемблере Z80 строки отформатированы следующим образом:

Круглые скобки «()» используются для обозначения того, что 16-битный аргумент или регистровая пара внутри не используются напрямую, но они используются в качестве указателя памяти для извлечения / сохранения 8- или 16-битного значения. Исключением из этого правила является JP-команда, в которой скобки следует игнорировать в логическом смысле, то есть «JP (HL)» логически работает как «JP HL»

Источник

Ассемблер для начинающих

В любом деле главное — начать. Или вот еще хорошая поговорка: «Начало — половина дела». Но иногда даже не знаешь как подступиться к интересующему вопросу. В связи с тем, что воспоминания мои еще свежи, спешу поделиться своими соображениями с интересующимися.

Скажу сразу, что лично я ассемблирую не под PC, а под микроконтроллеры. Но это не имеет большого значения, ибо (в отличие от микроконтроллеров AVR) система команд данных микроконтроллеров с PC крайне схожа. Да и, собственно говоря, ассемблер он и в Африке ассемблер.

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

Для начала успокою любознательных новобранцев: ассемблер — это совсем не сложно, вопреки стереотипному мнению. Просто он ближе к «земле», то бишь к архитектуре. На самом деле, он очень прост, если ухватить основную идею. В отличие от языков высокого уровня и разнообразных специализированных платформ для программирования (под всем перечисленным я понимаю всякое вроде C++, MatLAB и прочих подобных штук, где требуются программерские навыки), команд тут раз-два и обчелся. По началу даже, когда мне нужно было посчитать двойной интеграл, эта задача вызывала лишь недоумение: как при помощи такого скудного количества операций можно совершить подобную процедуру? Ведь образно говоря, на ассемблере можно разве что складывать, вычитать и сдвигать числа. Но с помощью ассемблера можно совершать сколь угодно сложные операции, а код будет выходить крайне лёгкий. Вот даже для примера, нужно вам зажечь светодиод, который подключен, например, к нулевому контакту порта номер 2, вы просто пишете:
bset P2.0
И, как говорится, никаких проблем. Нужно включить сразу штуки четыре, подключенных последовательно? Да запросто:
mov P2, #000fh
Да, тут я подразумеваю, что начинающий боец уже знаком хотя бы со системами счисления. Ну хотя бы с десятичной. 😉

Итак, для достижения успеха в деле ассемблирования, следует разбираться в архитектуре (в моем случае) микроконтроллера. Это раз.

Кстати, одно из больных мест в познании архитектуры — это организация памяти. Тут на Хабре я видела соответствующую статью: habrahabr.ru/blogs/programming/128991. Еще могу упомянуть ключевые болевые точки: прерывания. Штука не сложная, но по началу (почему-то) тяжелая для восприятия.

Если перед вами стоит сложная задача и вы даже не знаете как по началу к ней подступиться, лучше всего написать алгоритм. Это воистину спасает. А по началу, даже если программа совершенно не сложная, лучше всё же начать с алгоритма, ибо этот процесс помогает разложить всё в голове по местам. Возвращаясь к примеру с вычислением двойного интеграла по экспериментальным данным, обдумывала алгоритм я весь день, но зато потом программку по нему написала всего за 20 минут. Плюс алгоритм будет полезен при дальнейшей модернизации и/или эксплуатации программы, а то ассемблерный код, временами, если и будет понятен построчно, то чтобы разобраться в чем же общая идея, придется немало потрудиться.

Итак, второй ключ к успеху — подробно написанный и хорошо продуманный алгоритм. Настоятельно рекомендую не садиться сразу за аппарат и писать программу. Ничего дельного вы с ходу не напишете. Это два.

Собственно, хотелось бы как Фандорин написать: «Это т-т-три»… Но, боюсь, на этом пока можно остановиться. Хотя хотелось бы добавить еще несколько рекомендаций и пряников.

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

А теперь обещанные пряники! Вот я тут распинаюсь о каком-то непонятном ассемблере, а что же в нем, собственно говоря, хорошего? Да много всего! Во-первых, конечно, не нужно запоминать много команд, используемых библиотек и прочей сопутствующей дребедени. Всего парочка команд и, считайте, вы во всеоружии. Во-вторых, в связи с крайней близостью к машинным кодам, вы можете делать практически всё, что душе угодно (в отличие от тех же языков высокого уровня)! В-третьих, ассемблерный код, по причине максимальной лаконичности в формулировках, выполняется крайне быстро.

В общем, сплошные плюсы. На этой оптимистической ноте разрешите откланяться.

Источник

Поделиться с друзьями
admin
Оцените автора
( Пока оценок нет )
Как переводится?
Adblock
detector