Ассемблер для новичков

Язык ассемблер для начинающих

Эта статья предназначена для тех, кто только начинает изучать язык ассемблера. Довольно часто можно встретить книги и статьи с заголовками вроде «Ассемблер это просто». Подобные слоганы — не более чем маркетинговый ход — нужно как-то привлекать клиентов (читателей). Конечно, научиться писать простые программы очень легко. Но все зависит от задач, которые вы перед собой ставите. Научиться водить машину легко. Однако бывает только один водитель-ас.

Подготовка к работе

Думаю, вы уже знакомы с программированием — вы знаете любой из языков высокого уровня (C, PHP, Java, JavaScript и т. д), Вы работали с шестнадцатеричными числами, плюс вы знаете, как использовать командную строку в Windows , Linux или macOS.

На каком процессоре лучше всего учить язык если набор инструкций у всех разный?

Знаете ли вы что такое 8088? Это дедушка всех компьютерных процессоров! И живой дедушка. Я бы сказал — бессмертный и постоянный. Если из вашего процессора, будь то Ryzen, Core i9 или какого-то другого типа, вырвите все застрявшие там гаджеты под влиянием технического прогресса, то старый добрый 8088 останется.

SGX, ММХ, 512-битные регистры SIMD и другие нововведения приходят и уходят.Но дедушка 8088 остался без изменений. Сначала подружитесь с ним. Тогда вы легко справитесь с любыми гаджетами вашего процессора.

Когда же вам придется начать с самого начала, то есть сначала выучить классический набор инструкций 8088, а затем постепенно познакомитесь с современными функциями — в какой-то момент вы начнете видеть нестандартные способы использования этих самых функций.

Какие процессы происходят в процессоре после того, как ты запускаешь программу.

После запуска программного обеспечения и загрузки его операционной системой в ОЗУ процессор обращается к первому байту программы. Выцепляет инструкцию оттуда и выполняет ее, а после ее выполнения переходит к следующей. И так до конца программы.

Некоторые инструкции имеют объем в один байт, а некоторые – в два, три или больше.Это выглядит как то так:

90
B0 77
B8 AA 77
C7 06 66 55 AA 77

Вернее, даже так:

90 B0 77 B8 AA 77 C7 06 66 55 AA 77

И только машина способна понять такое.Так что еще несколько лет назад разработчики придумали более гуманный способ общения с компьютером: они создали ассемблер.

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

nop
mov al, 0x77
mov ax, 0x77AA
mov word [0x5566], 0x77AA

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

Зачем нужны регистры процессора и как ими пользоваться.

Какие функции выполняет инструкция Mov? Присваивает число, которое указано справа, переменной, которая указана слева.

Регистр процессора или ячейка ОЗУэто одна из переменных в памяти компьютера. Процессор быстрее работает с регистрами, чем с памятью, потому что регистры находятся внутри него. Но у процессора мало регистров, поэтому в любом случае что-то нужно хранить в памяти.

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

У процессора 8088 регистры 16-битные, их восемь штук (в скобках указаны типичные способы применения регистра):

  • AXобщего назначения (аккумулятор);
  • BX — общего назначения (адрес);
  • CX — общего назначения (счетчик);
  • DX — общего назначения (расширяет AX до 32 бит);
  • SI — общего назначения (адрес источника);
  • DI — общего назначения (адрес приемника);
  • BP — указатель базы (обычно адресует переменные, хранимые на стеке);
  • SP — указатель стека.

Хотя каждый регистр имеет типичный вариант использования, вы можете использовать их как хотите. Первые четыре регистра — AX, BX, CX и DX — при желании можно использовать не полностью, а половинками по 8 бит (старший H и младший L): AH, BH, CH, DH и AL, BL, CL, DL. Например, если вы напишете в AX число 0x77AA (mov ax, 0x77AA), то 0x77 попадет в AH, а 0xAA — в AL.

Теория пока закончена. Сейчас мы с тобой подготовим рабочее место и напишем программу «Hello World!» для того, чтобы понять, как эта теория работает на практике.

Подготовка рабочего места

  1. Скачай компилятор NASM с www.nasm.us. Обрати внимание, он работает на всех современных ОС: Windows 10, Linux, macOS. Распакуй NASM в какую-нибудь папку. Чем ближе папка к корню, тем удобней. У меня это c:\nasm (я работаю в Windows). Если у тебя Linux или macOS, можешь создать папку nasm в своей домашней директории.

  2. Тебе надо как-то редактировать исходный код. Ты можешь пользоваться любым текстовым редактором, который тебе по душе: Emacs, Vim, Notepad, Notepad++ — сойдет любой. Лично мне нравится редактор, встроенный в Far Manager, с плагином Colorer.

  3. Чтобы в современных ОС запускать программы, написанные для 8088, и проверять, как они работают, тебе понадобится DOSBox или VirtualBox.

Пишем, компилируем и запускаем программу «Hello, world!»

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

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

Если вы не понимаете, что здесь написано, не волнуйтесь. А пока попробуйте к ассемблерному коду привыкнуть, пощупайте пальцами. Я все объясню ниже. Кроме того, студенческая мудрость гласит: «Ты что-нибудь понимаешь? Перечитал и переписал несколько раз. Сначала непонятное станет знакомым, а потом знакомое станет понятным. «

Для запуска командной строки, в Windows есть cmd.exe. Теперьнужно зайти в папку nasm и скомпилировать программу, используя вот такую команду:

nasm -f bin first.asm -o first.com

Если все сделано правильно то она не будет вызывать никаких проблем с компиляцией и запуском, и в командной строке не появится никаких сообщений. NASM просто создаст файл first.com и выйдет.

Чтобы запустить этот файл в современной ОС, открой DOSBox и введи туда вот такие три команды:

mount c c:\nasm
c:
first

Само собой, вместо c:\nasm тебе надо написать ту папку, куда ты скопировал компилятор. Если ты все сделал правильно, в консоли появится сообщение «Hello, world!».

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

Инструкции и директивы

В нашей программе есть только три вещи: инструкции, директивы и метки.

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

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

Директива org сообщает компилятору, что все последующие инструкции не должны размещаться в начале сегмента кода, а должны отклоняться от начала такого количества байтов (в нашем случае 0x0100).

Директива db указывает компилятору вставить байтовую строку в ваш код. Здесь мы указываем через запятую, что туда помещать. Это может быть строка (в кавычках), символ (в одинарных кавычках) или просто число.

В нашем случае: db "Hello, world", '!', 0.

Убедитесь, что я вырезал восклицательный знак на остальной части строки, чтобы показать, что вы можете работать с отдельными символами в директиве db. В общем, лучше писать так:

db "Hello, world!", 0

Условные, безусловные переходы и метки

Метки используются для двух целей: для задания имен переменных, которые хранятся в памяти (в нашей программе есть только одна такая метка: string), и для обозначения участков кода, в которых вы переходите из других мест в программе ( В нашем ассортименте три таких лейбла — те, которые начинаются с двух символов-собак).

Что значит «прыгать с других мест в программе»? Процессор обычно выполняет инструкции последовательно, одну за другой. Но если вы хотите организовать ветвление (условие или цикл), вы можете использовать инструкцию ветвления. Вы можете перейти вперед от текущей инструкции или назад.

У тебя в распоряжении есть одна инструкция безусловного перехода (jmp) и штук двадцать инструкций условного перехода.

Мы используем две инструкции перехода: je и jmp. Первый выполняет условный переход (Jump if equal — прыгать, если равен), второй (Jump) — безусловный. С их помощью мы организовали цикл.

Обратите внимание, что метки начинаются с буквы, подчеркивания или собаки. Вы также можете вставлять числа, но не в начале. В конце метки необходимо поставить двоеточие.

Выбор регистров, алгоритм и комментарии

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

Как добавлять комментарии? Просто поставьте точку с запятой, и все, что вы напишете после нее (до конца строки), будет комментарием. Добавим комментарии к нашей программе.

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

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

  1. Поместить в BX адрес строки.
  2. Поместить в AL очередную букву из строки.
  3. Если вместо буквы там 0, выходим из программы — переходим на 6-й шаг.
  4. Выводим букву на экран.
  5. Повторяем со второго шага.
  6. Конец.

Мы не можем использовать AX для хранения адресной информации, так как нет таких инструкций, которые бы использовали его в качестве регистра-источника.

Данные с клавиатуры

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

Потом иди в командную строку и скомпилируй его в NASM:

nasm -f bin second.asm -o second.com

Затем запусти скомпилированную программу в DOSBox:

second

Как работает программа? Две строки после метки @@ start вызывают функцию BIOS, которая считывает символы с клавиатуры. Он ожидает, пока пользователь нажмет клавишу, а затем помещает ASCII-код полученного значения в регистр AL. Например, если вы нажмете заглавную A, 0x41 попадет в AL, а если вы нажмете заглавную a, 0x61.

Затем смотрим: если нажата клавиша с кодом 0x1B (клавиша ESC), мы выходим из программы. Если клавиша ESC не нажата, мы вызываем ту же функцию, что и в предыдущей программе, чтобы показать символ на экране. После показа — перейти в начало (jmp): start.

На заметку, инструкция cmp (от слова Compareсравнивать) выполняет сравнение, инструкция je(Jump if Equal) прыжок в конец программы.

Автоматизируем компиляцию и смотрим машинный код

Если тебе интересно, в какой машинный код преобразуются инструкции программы, скомпилируй исходник вот таким вот образом (добавь опцию -l):

nasm -f bin second.asm -l second.lst -o second.com

Тогда NASM создаст не только исполняемый файл, но еще и листинг: second.lst. Листинг будет выглядеть как-то так.

Вы, наверное, уже устали вводить длинную последовательность одних и тех же букв в командную строку каждый раз при компиляции. Если вы используете Windows, вы можете создать командный файл (например, m.bat) и вставить в него следующий текст.

Теперь ты можешь компилировать свою программу вот так:

m first

Само собой, вместо first ты можешь подставить любое имя файла.

Выводы

В общем теперь ты знаешь как написать простейшю программе на ассемблере как ее скомпилировать и какие средства для этого нужны. Однако, если ты прочтешь одну статью, то вряд ли станешь настоящим программистом на ассемблере.Чтобы создать и написать на нем что-то действительно стоящее например, Floppy Bird и “МикроБ”, тебе еще придется немало потрудиться. Но это уже твой первый шаг в этом направлении.

 

 


 

 

 

 

 

 

 

Click to rate this post!
[Total: 0 Average: 0]

Leave a reply:

Your email address will not be published.