Справочник от Автор24
Поделись лекцией за скидку на Автор24

Ассемблер и язык ассемблера

  • 👀 419 просмотров
  • 📌 373 загрузки
Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Ассемблер и язык ассемблера» docx
§ 1.1. Ассемблер и язык ассемблера «Сердцем» компьютера является процессор. С точки зрения программирования процессор – это «маленькая коробка», которой можно посылать команды и ждать результат. Для того чтобы процессор мог исполнить программу, исходный текст программы должен преобразовываться (кем? – системой программирования) в исполняемый модуль – именно он будет загружаться в память на выполнение. Исполняемый модуль (исполняемая программа) – это последовательность кодов команд процессора и кодов данных, то есть последовательность чисел (в двоичном коде) – машинный код. Пример: exe-файлы. Язык ассемблера – это ЯП, позволяющий писать исходную программу непосредственно на уровне команд процессора – это ЯП низкого уровня. Инструкции (команды) языка ассемблера соответствуют командам процессора: каждой команде процессора сопоставлена англоязычная аббревиатура (инструкция) языка ассемблера. Существуют различные модели процессоров со своим собственным набором команд. Þ Существуют разновидности (диалекты) языка ассемблера. Не важно, язык какого именно ассемблера изучать. Главное понять принцип работы на уровне команд процессора. Тогда не составит труда освоить не только другой язык ассемблера, но и любой другой процессор со своим набором команд. В лекциях рассматривается система команд процессоров Intel. Трансляция (ассемблирование) – преобразование записанных на языке ассемблера инструкций и данных в машинные коды. Ассемблер – программа-транслятор – программа, которая выполняет трансляцию в машинные коды. Дизассемблер – программа, выполняющая обратную задачу: переводит машинные коды в ассемблерные инструкции. int i = 5; mov dword ptr [i], 5 c7 45 f8 05 int j = 2; mov dword ptr [j], 2 c7 45 ec 02 j = j + i; mov eax, dword ptr [j] 8b 45 ec add eax, dword ptr [i] 03 45 f8 mov dword ptr [j], eax 89 45 ec Отличие ассемблеров от компиляторов Трансляторы с языка ассемблера и компиляторы с ЯПВУ выполняют одну задачу: получить машинный код из исходного текста программы. Принципиальное отличие: • Транслятор преобразует одну инструкцию языка ассемблера в одну машинную команду – преобразование «один к одному». • Компилятор с ЯПВУ преобразует один оператор языка в последовательность из нескольких машинных команд – преобразование «один к нескольким». Чем «выше» уровень ЯП, тем к большему числу команд процессора будут преобразовываться операторные конструкции языка. Кроме инструкций для процессора, в языке ассемблера есть служебные указания для транслятора – директивы. Их используют в исходном тексте программы для описания её структуры, форматов данных, управления трансляцией и т.д. Место языка ассемблера в программировании 1. Там, где нужен прямой программный доступ к памяти и аппаратуре. 2. Для создания минимальной по размеру и/или минимальной по времени исполнения программы. С помощью ассемблерных вставок часто оптимизируют отдельные фрагменты программ на ЯПВУ. На практических занятиях программы на языке ассемблера необходимо будет реализовать как ассемблерные вставки на языке C/C++. 3. Это инструмент анализа исполняемых программ при отсутствии их исходных текстов. 4. Это уникальный учебный инструмент для понимания механизмов взаимодействия процессора с памятью и устройствами вычислительной системы. #include int main(){ int i = 5; int j = 2; //j = j + i; _asm{ mov eax,i add eax,j mov i,eax } printf("%i", i); return 0; } Часто вместо «язык ассемблера» говорят «ассемблер». § 1.2. Представление данных Двоичная система счисления Чтобы отличать двоичные числа от десятичных, в ассемблерных программах в конце каждого двоичного числа ставят букву «b». 10010110b = 1×27+0×26+0×25+1×24+0×23+1×22+1×21+0×20 = 150 Остаток Разряд 150/2 = 75 75/2 = 37 37/2 = 18 18/2 = 9 9/2 = 4 4/2 = 2 2/2 = 1 1/2 = 0 1 1 1 1 1 2 3 4 5 6 7 Результат: 10010110b 1 1 1 1 7 6 5 4 3 2 1 байт 1 1 1 1 15 8 7 слово старший байт младший байт aдрес (x+1) aдрес (x) Шестнадцатеричная система счисления В ассемблерных программах при записи чисел, начинающихся с А, В, С, D, E, F, в начале приписывается цифра 0, чтобы нельзя было спутать такое число с названием переменной или другим идентификатором. После шестнадцатеричных чисел ставится буква «h». 1 2 3 4 5 6 7 0000b 0001b 0010b 0011b 0100b 0101b 0110b 0111b 0h 1h 2h 3h 4h 5h 6h 7h 8 9 10 11 12 13 14 15 1000b 1001b 1010b 1011b 1100b 1101b 1110b 1111b 8h 9h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh Перевод в двоичную систему и обратно: вместо каждой шестнадцатеричной цифры подставляют соответствующее четырехзначное двоичное число: 10010110b = 96h 0ADh = 10101101b 16 = 10000b = 10h Целые числа со знаком Для представления отрицательных чисел существует специальная операция, известная как дополнение до двух. Для изменения знака числа выполняют инверсию, то есть заменяют в двоичном представлении числа все единицы нулями и нули единицами, а затем прибавляют 1. 150 = 0000000010010110b = 0096h инверсия дает: 1111111101101001b +1 = 1111111101101010b = 0FF6Ah Проверим, что полученное число на самом деле -150: сумма с +150 должна, быть равна нулю: +150 + (-150) = 0096h + 0FF6Ah = = 10000h = 10000000000000000b Единица в l6-м разряде не помещается в слово, и значит, мы действительно получили 0. § 1.3. Организация памяти Структура вычислительной системы: • Байты памяти, • регистры и • порты контроллеров – «источники» данных для системы команд процессора. Память – последовательность байт – единое адресное пространство. Каждый байт имеет уникальный (физический) адрес: 0, 1, 2, 3, и т.д. Байт – минимальная «единица» чтения или записи в память. Регистры – специальные ячейки высокоскоростной памяти, расположенные физически внутри процессора. Доступ к регистрам осуществляется не по адресам, а по именам. Разрядность регистров: 8, 16, 32, 64 бит. Порты – это регистры внутри контроллеров. Разрядность: 8 бит. С памятью процессор связан несколькими шинами: • На шину адреса процессор «выставляет» адрес памяти. • По шине данных затем считывает данные из памяти в регистр или записывает из регистра в память. От разрядности шины адреса зависит объем памяти, которую может адресовать процессор: 2N байтов, где N – разрядность адресной шины. Для процессоров с 32-разрядной адресной шиной объем физически адресуемой памяти составляет 232 байтов (4 Гб): от 0 до 232 – 1 . Чтение из памяти слова, начиная с адреса 120: Основные принципы архитектуры фон-Неймана: 1. Линейное пространство памяти: оперативная память представляет собой совокупность ячеек с последовательной нумерацией (физическими адресами) 0, 1, 2, ... 2. Принцип хранимой программы: код программы и ее данные находятся в одном и том же адресном пространстве памяти. 3. Отсутствие разницы между данными и командами в памяти: с точки зрения процессора и данные, и команды – это последовательности 0 и 1. 4. Последовательное выполнение программы. Процессор после включения питания оказывается в режиме реальной адресации памяти, или просто реальном режиме. Операционная система переводит его в защищенный режим, позволяющий обеспечивать многозадачность, распределение памяти и др. Пользовательские программы часто работают в виртуальном режиме, из которого им доступно все то же, что и из реального, кроме инструкций, относящихся к управлению защищенным режимом... Измерение объемов памяти в более крупных единицах: 1 Килобайт = 1024 байтов (210 байтов), 1 Мегабайт = 1024 Кб (220 байтов); 1 Гигабайт = 1024 Мб (230 байтов); 1 Терабайт = 1024 Гб (240 байтов). § 1.4. Регистры Группа регистров Назначение 1. Основные 1.1. Общего назначения (8): eax, ebx, ecx, edx, esi, edi, ebp, esp Хранение данных и адресов 1.2. Сегментные (6): cs, ds, es, fs, gs, ss Хранение адресов сегментов памяти 1.3. Состояния и управления (2): eip, eflags 2. Сопроцессора: sf(0), sf(1), …, sf(7) Работа с числами с плавающей точкой 3. MMX-расширения 4. Системные Регистры общего назначения eax/ax/ah/al ebx/bx/bh/bl ecx/cx/ch/cl edx/dx/dh/dl esi/si edi/di ebp/bp esp/sp Младшие 16 бит каждого из 32-разрядных (32-битных) регистров общего назначения могут использоваться как самостоятельные регистры и имеют имена. Отдельные байты в первых четырех 16-битных регистрах тоже имеют свои имена и могут использоваться как 8-битные регистры. -x e- -h -l 31 16 15 8 7 Буквы в названии регистра и их обозначения e- Extended – 32 бита -h High – старшие 8 бит -x eXtended – 16 бит -l Low – младшие 8 бит eax, ebx, ecx, edx могут использоваться для хранения данных и адресов. Названия этих регистров происходят от того, что некоторые инструкции применяют их специальным образом: • либо использование какого-то регистра обязательно, • либо происходит неявно. Аккумулятор (Accumulator register) ax eax ah al 31 16 15 8 7 Для хранения промежуточных данных. В некоторых инструкциях используется обязательно. База (Base register) bx ebx bh bl 31 16 15 8 7 Для хранения базового адреса некоторого объекта в памяти. Счетчик (Count register) cx ecx ch cl 31 16 15 8 7 В инструкциях, производящих повторяющиеся действия. Регистр данных (Data register) dx edx dh dl 31 16 15 8 7 Применяется для хранения промежуточных данных. Следующие 4 регистра имеют более конкретное назначение и могут применяться для хранения всевозможных временных данных, только когда они не используются по назначению. Индекс источника (Sourse Index register) esi si 31 16 15 Индекс приемника (Destination Index register) edi di 31 16 15 esi и edi используются в паре в строковых (цепочечных) инструкциях: esi содержит текущий адрес элемента в цепочке-«источнике», edi содержит текущий адрес элемента в цепочке-«приемнике». Указатель базы (Base Pointer register) ebp bp 31 16 15 Указатель стека (Stack Pointer register) esp sp 31 16 15 ebp и esp используются при работе со стеком: esp содержит адрес вершины стека. Сегментные регистры Сегментированная модель памяти: программы работают с памятью как с несколькими непрерывными последовательностями байт – сегментами. Для задания физического адреса байта требуется два числа: • адрес начала сегмента – база (селектор), • адрес байта внутри сегмента – смещение (эффективный адрес). физический адрес = база : смещение Процессор аппаратно поддерживает организацию программы в виде 3-х частей: сегмент стека, сегмент кода и сегмент данных. 1) сегмент стека – содержит временные данные (параметры вызываемых подпрограмм, локальные переменные, адреса возврата); 2) сегмент кода – содержит команды исполняемой программы; 3) сегмент данных – содержит обрабатываемые программой данные. Сегментные регистры содержат адреса памяти, с которых начинаются соответствующие сегменты. Регистр сегмента стека (Stack Segment register) ss 15 Регистр сегмента кода (Code Segment register) cs 15 Регистры сегмента данных (Data Segment register) ds es fs gs 15 Регистр eip и адресное пространство памяти Адрес «следующей выполняемой команды» всегда хранится в специальном регистре eip (относится к регистрам состояния и управления). Программисту не доступен. Указатель команды Instruction Pointer register eip ip 31 16 15 После чтения команды из памяти значение в eip аппаратно увеличивается на длину прочитанной команды в байтах. Если быть точнее, в eip хранится не физический адрес, а смещение следующей выполняемой команды. В регистре esp также хранится смещение, а не физический адрес. сs:eip – физический адрес следующей выполняемой команды ss:esp – физический адрес вершины стека При записи в стек значение смещения уменьшается, то есть стек растет вниз от максимально возможного адреса. При вызове подпрограммы параметры в большинстве случаев помещают в стек, а в ebp записывают текущее значение esp. Тогда, если подпрограмма использует стек для хранения локальных переменных, esp изменится, но ebp можно будет использовать для того, чтобы считывать значения параметров напрямую из стека (их смещения будут записываться как ebp + номер параметра). Регистр флагов Используется при выполнении большинства инструкций (относится к регистрам состояния и управления). Регистр флагов (Flag register) eflags flags 31 16 15 В этом регистре каждый бит является флагом: устанавливается в 1 при определенных условиях или установка его в 1 изменяет поведение процессора. Младшее слово регистра флагов (регистр flags) nt iopl of df if tf sf zf af pf 1 cf 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 cf – флаг переноса. Устанавливается в 1, если результат выполненной арифметической операции не уместился в «приемнике» и произошел перенос из старшего бита или если требуется заем (при вычитании), иначе устанавливается в 0. При работе с числами без знака равенство 1 сигнализирует об ошибке. zf – флаг нуля. Устанавливается в 1, если результат выполненной инструкции равен нулю. sf – флаг знака. Этот флаг всегда равен старшему биту результата. of – флаг переполнения. Этот флаг устанавливается в 1, если результат выполненной арифметической операции над числами со знаком выходит за допустимые для них пределы. При работе с числами со знаком равенство 1 сигнализирует об ошибке. Перенос из разрядной сетки Перенос в знаковый бит Флаги + + cf = 1, of = 0 + - cf = 1, of = 1 - + cf = 0, of = 1 - - cf = 0, of = 0 Пусть складываются два числа со знаком 110 = 012 + -110 = 112 (в дополнительном коде) 0 = 1002 (+ +) cf = 1, of = 0 ошибки нет 110 = 012 + 110 = 012 2 ? 112 = -110 (- +) cf = 0, of = 1 ошибка 30566 = 0111011101100110b + 30566 = 0111011101100110b 61132 = 1110111011001100b (- +) cf = 0, of = 1 Произошел перенос из 14-го разряда, из 15-го разряда переноса нет. Ошибка, т.к. переполнение: 16-битное число со знаком максимум +32767. -30566 = 1000100010011010b + -04875 = 1110110011110101b -35441 = 10111010110001111b (+ -) cf = 1, of = 1 Произошел перенос из 15-го разряда. Ошибка, так как старший бит 0 и ответ получился положительным. -4875 = 1110110011110101b + -4875 = 1110110011110101b -9750 = 11101100111101010b (+ +) cf = 1, of = 0 Есть переносы из 14-го и 15-го разрядов. Ошибки нет. pf – флаг четности (паритета). Устанавливается в 1, если младший байт результата выполненной команды содержит четное число бит, равных 1; устанавливается в 0, если число единичных бит нечетное. af – флаг полупереноса или вспомогательного переноса. Устанавливается в 1, если в результате выполнения команды произошел перенос (или заем) из третьего бита в четвертый. Этот флаг используется автоматически командами двоично-десятичной коррекции. tf – флаг трассировки. Этот флаг был предусмотрен для работы отладчиков, не использующих защищенный режим. Установка его в 1 приводит к тому, что после выполнения каждой команды программы управление временно передается отладчику (вызывается прерывание № 1). if – флаг прерываний. Установка этого флага в 1 приводит к тому, что процессор перестает обрабатывать прерывания от внешних устройств. Обычно его устанавливают на короткое время для выполнения критических участков кода. df – флаг направления. Этот флаг контролирует поведение команд обработки строк – когда он установлен в 1, строки обрабатываются в сторону уменьшения адресов, а когда = 0 – наоборот. Флаги iopl (уровень привилегий ввода-вывода) и nt (вложенная задача) применяются в защищенном режиме. Все флаги, расположенные в старшем слове регистра, имеют отношение к управлению защищённым режимом.
«Ассемблер и язык ассемблера» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot