Как я изучал ассемблер: добрые советы будущим товарищам по несчастью - Студенческий научный форум

XI Международная студенческая научная конференция Студенческий научный форум - 2019

Как я изучал ассемблер: добрые советы будущим товарищам по несчастью

Муравьев Е.Г. 1, Абрамова О.Ф. 1
1Волжский политехнический институт(филиал) ВолгГТУ
 Комментарии
Текст работы размещён без изображений и формул.
Полная версия работы доступна во вкладке "Файлы работы" в формате PDF

В ходе понимания самой сути программирования как творческой, так и коммерческой деятельности, каждый программист приходит к справедливому выводу, что использование языков высокого уровня предпочтительнее целеустремленным попыткам познать весьма непростую область – среду программирования языков более низкого уровня – и в итоге стать «ближе» к ЭВМ и понимать её с компромиссной точки зрения. Однако, как показывает практика, чем больше нас увлекает программирование, тем становится яснее мысль о необходимости познания того, с чем и как мы с этим работаем на аппаратном уровне, вникая во все механизмы регуляции процессов, протекающих в программируемых машинах. Именно для удовлетворения такой необходимости следует с самых ранних этапов стараться понемногу вникать в суть низкоуровнего программирования, и одним из языков такого уровня является язык Assembler.

Само слово ассемблер (assembler) переводится с английского как «сборщик». Изначально нужно понимать, что ассемблером принято называть программу-транслятор, которая принимает текст, содержащий условные обозначения машинных команд, и переводит его на понятный процессору машинный код. Такие условные обозначения (также называемые «мнемониками») позволяют понять суть той команды, которую необходимо выполнить процессору. К тому же, для ещё большего упрощения, все эти мнемоники образованы от английских слов. Язык условных обозначений также называется ассемблером [3].

Таким образом, ассемблер – это машинно-ориентированный язык программирования, позволяющий работать с компьютером напрямую, один на один. Отсюда и его полная формулировка – язык программирования низкого уровня второго поколения (после машинного кода). Команды ассемблера один в один соответствуют командам процессора, но поскольку существуют различные модели процессоров со своим собственным набором команд, то, соответственно, существуют и разновидности, или диалекты, языка ассемблера. Поэтому использование термина «язык ассемблера» может вызвать ошибочное мнение о существовании единого языка низкого уровня или хотя бы стандарта на такие языки. Его не существует. Поэтому при именовании языка, на котором написана конкретная программа, необходимо уточнять, для какой архитектуры она предназначена и на каком диалекте языка написана. Поскольку ассемблер привязан к устройству процессора, а тип процессора жестко определяет набор доступных команд машинного языка, то программы на ассемблере не переносимы на иную компьютерную архитектуру [3].

Помимо сложности понимания механизма взаимодействия компонентов внутри машины, процесс изучения машинно-зависимых языков усугубляется ещё и его непопулярностью. Обусловливается этот факт тем, что, как правило, к языкам низкого уровня «спускаются» с языков высокого уровня. Восприятие, сформированное на этапе изучения типизированных языков программирования, имеет иные представления о строении программ, о том, как они работают и как компьютер воспринимает их. Таким образом, уже сформировавшиеся знания идут в конфронтацию с новыми, предлагаемыми языками, близкими к машинно-зависимым.

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

Система рекомендаций:

1. Регистры

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

Главное, что необходимо запомнить на ранних этапах изучения ассемблера, это классификацию регистров и их назначения.

Регистры принято разделять на четыре группы:

Универсальные регистры (РОН): AX, BX, CX, DX

Указательные и индексные регистры: SP, BP, SI, DI

Сегментные регистры: CS, DS, SS, ES

Регистр указателя команд IP и регистр флагов FL

В контексте данной статьи, продуктивным решением будет считаться рассмотрение регистров только первой группы. Каждый регистр из этой группы обладает специфичным строением: каждый 32-разрядный регистр типа POH(EAX, EBX, ECX, EDX) обладает своей младшей 16-разрядной частью – AX, BX, CX и DX. В свою очередь, эти 16-разрядные части допускают независимое использование своих младших и старших половин, то есть фактически 8-разрядных регистров (AH и AL, CH и CL и т.д.) [2, c. 18].

2. Системы счисления

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

Такой подход может показаться сложным и требующим определенных навыков со стороны желающих работать в рассматриваемой среде программирования. Единственно дельным советом тут может послужить рекомендация к внимательному рассмотрению принципов вычислений в тех системах счисления, которые необходимы для решения той или иной задачи [2, c. 10-11].

3. Адресация структур данных

Адресацией называют процедуру нахождения необходимого операнда. Для нахождения нескольких операндов должно существовать столько же способов адресации [1]. Существует множество видов адресации, но каждый из них представляет собой так называемый эффективный адрес – выражение, в сумме которого получается адрес искомого операнда. Данное выражение имеет вид [5]:

EA (эффективный адрес) = база + смещение + (индекс*множитель) где:

база – адрес ячейки памяти, от которого необходимо производить отсчет

смещение – 8- или 32-разрядная величина

индекс – значение для перехода к необходимой ячейке

Для наглядности приведём пример обращения к элементам массива в рядовой задаче, выполненную на языке высшего уровня C и языке ассемблер:

Задача: в квадратной матрице 3x3 найти максимальный элемент в каждой строке.

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

1

2

3

4

5

6

7

8

9

Как же нам обратиться к элементу, необходимому нам, допустим, к 5?

Для обоих языков синтаксис будет примерно идентичен:

Си: Ассемблер:

i = 2, j = 2; mov cl, 2

a = mas[i][j]; // вазаносим 5 mov bx, 2

mov al, mas[cl][bx] ; заносим 5 врегистр al

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

mov cl, 4

mov al, mas[cl]

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

4. Метки

Под меткой можно понимать некий участок кода, который необходимо отметить – выделить для определенной цели. Метки в ассемблере предназначены для регулирования хода выполнения команды. Они тесно связаны с такими понятиями, как условный и безусловный переход. Как следует из названия, это переходы с условием и без него, т.е. в любом случае, соответственно. Пример синтаксиса меток очень прост [4]:

---- Инструкция Ассемблера ----

Metka1: ; это метка

---- Инструкция Ассемблера ----

Метки необходимы, когда в программе нужно организовать циклы и/или ветвления. Каждый из видов перехода имеет свой набор команд, с помощью которых эти переходы осуществляются.

Таким образом, рассмотренный материал может помочь читателю легче преодолеть трудности, лежащие на пути изучения такой интересной, но не приветливой для субъекта познания дисциплины, как ассемблер. Погружаясь всё глубже и глубже в эту сферу программирования, Вы начнёте понимать, что хоть использование ассемблера требуется достаточно редко, эти пускай не частые ситуации могут повлиять на быстродействие программы, что укрепит в окружающих представление о Вас, как о профессиональном программисте.

Список литературы:

Ассемблеры. Режимы адресации [Эл. ресурс]. URL: https://studfiles.net/preview/4349789/page:5/

Калашников О. А. Ассемблер? Это просто! Учимся программировать. – СПб.: БХВ-Петербург, 2005. – 384 с.

Погружение в assembler. Полный курс по программированию [Эл. ресурс]. URL: https://xakep.ru/2017/09/11/asm-course-1/

Учебный курс. Часть 16. Условные и безусловные переходы [Эл. ресурс]. URL: http://asmworld.ru/uchebnyj-kurs/016-uslovnye-i-bezuslovnye-perexody/

Эффективный адрес [Эл. ресурс]. URL: http://ru.osdev.wikia.com/ wiki/Эффективный_адрес

Просмотров работы: 27