Tooprogram.ru

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Сегментация памяти ассемблер

Сегментация памяти, директивы ассемблера

Любые ассемблерные программы содержат, по крайней мере, один сегмент: сегмент кода. В некоторых программах используется сегмент для стековой памяти и сегмент данных для определения данных. Ассемблерная директива для описания сегмента SEGMENT имеет следующий формат:

Имя сегмента обязательно, оно должно быть уникальным. Директива ENDS означает конец сегмента.

Пример оформления сегмента данных с именем “data”:

AB dW 3145h, 1F4Ah

A3 dB “Абрикосовое дерево”

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

Формат директивы определения данных:

Имя элемента данных не обязательно, но если в программе есть ссылка на некоторый элемент данных, то это делается по средствам имени. Например: MOV AX, AB

Здесь содержимое слова по адресу AB (см. пример выше) пересылается в регистр AX. После выполнение этого оператора в AX будет записано число 3145h. Символическое имя AB является адресом определенной ячейки памяти. В нашем случае этот адрес равен 3, т.к. адресация в сегменте относительна к началу сегмента. Символическое имя А транслируется системой ассемблирования в значение равное 0. Это адрес первого байта в сегменте (содержимое его равно 35h). Далее определены еще два байта со значением 44 и 0FAh, следовательно, адрес AB вычисляется как 0+3 байта=3.

Команда MOV AL, А+2 загружает в регистр AL значение FA, команда MOV AX, AB+2 загружает в регистр AX значение 4456h.

DNв выражении (1) может иметь следующие мнемоники: DB (байт), DW (слово), DD (двойное слово), DQ (учетверенное слово), DT (10 байт).

Выражение может содержать константу, например:

Несколько констант: FL1 DB 11,12,25,84,91,… разделенных запятыми и ограниченных длиной строки.

Ассемблер определяет эти константы в виде последовательности смежных байтов. Ссылки по имени FL1 указывает на первую константу –11, по FL1+1, на вторую, равную 12.

Выражение может содержать знак вопроса для неопределенного значения: FL2 DW ?

Здесь резервируется два байта. Выражение допускает так же повторение константы в следующем формате:

Например: DW 10 DUP(?) ; 10 неопределенных слов

DB 5 DUP(14) ; 5 байт содержащих 0ЕН

DB 3 DUP (4 DUP(8)) ; 12 восьмерок.

Выражение может содержать символьную строку. Символьная строка используется для описания данных, таких, как, например, имена людей или заголовки страниц. Содержимое строки отмечается одиночными кавычками. Ассемблер переводит символьные строки в объективный код в обычном формате ASCII. Символьная строка определяется только директивой DВ: KSP DB ‘ТРАВОСТОЙ’

Если в программе необходимо изменить последнюю букву в слове ТРАВОСТОЙ на “П”, запишем оператор: MOV KSP+8, ‘П’.

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Для студентов недели бывают четные, нечетные и зачетные. 9950 — | 7737 — или читать все.

Организация и модели памяти, адресация

Память – способность объекта обеспечивать хранение данных.
Все объекты, над которыми выполняются команды, как и сами команды, хранятся в памяти компьютера.

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

Байты последовательно располагаются в памяти компьютера.

  • 1 килобайт (Кбайт) = 2 10 = 1 024 байт
  • 1 мегабайт (Мбайт) = 2 10 Кбайт = 2 20 байт = 1 048 576 байт
  • 1 гигабайт (Гбайт) = 2 10 Мбайт = 2 30 байт = 1 073 741 824 байт

Для доступа к памяти с целью записи или чтения отдельных элементов информации используются идентификаторы , определяющие их расположение в памяти. Каждому идентификатору в соответствие ставится адрес . В качестве адресов используются числа из диапазона от 0 до 2 k -1 со значением k, достаточным для адресации всей памяти компьютера.Все 2 k адресов составляют адресное пространство компьютера .

Способы адресации байтов

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

Прямым способом называется противоположная система адресации. Компиляторы высокоуровневых языков поддерживают прямой способ адресации.

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

Организация памяти

Физическая память, к которой микропроцессор имеет доступ по шине адреса, называется оперативной памятью ОП (или оперативным запоминающим устройством — ОЗУ).
Механизм управления памятью полностью аппаратный, т.е. программа сама не может сформировать физический адрес памяти на адресной шине.
Микропроцессор аппаратно поддерживает несколько моделей использования оперативной памяти:

  • сегментированную модель
  • страничную модель
  • плоскую модель

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

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

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

  • Сегмент кодов ( .CODE ) – содержит машинные команды для выполнения. Обычно первая выполняемая команда находится в начале этого сегмента, и операционная система передает управление по адресу данного сегмента для выполнения программы. Регистр сегмента кодов ( CS ) адресует данный сегмент.
  • Сегмент данных ( .DATA ) – содержит определенные данные, константы и рабочие области, необходимые программе. Регистр сегмента данных ( DS ) адресует данный сегмент.
  • Сегмент стека ( .STACK ). Стек содержит адреса возврата как для программы (для возврата в операционную систему), так и для вызовов подпрограмм (для возврата в главную программу). Регистр сегмента стека ( SS ) адресует данный сегмент. Адрес текущей вершины стека задается регистрами SS:ESP .
Читать еще:  Единицей измерения в системе си является

Регистры дополнительных сегментов ( ES, FS, GS ), предназначены для специального использования.

Для доступа к данным внутри сегмента обращение производится относительно начала сегмента линейно, т.е. начиная с 0 и заканчивая адресом, равным размеру сегмента. Для обращения к любому адресу в программе, компьютер складывает адрес в регистре сегмента и смещение — расположение требуемого адреса относительно начала сегмента. Например, первый байт в сегменте кодов имеет смещение 0, второй байт – 1 и так далее.

Таким образом, для обращения к конкретному физическому адресу ОЗУ необходимо определить адрес начала сегмента и смещение внутри сегмента.
Физический адрес принято записывать парой этих значений, разделенных двоеточием

сегмент : смещение

Страничная модель памяти – это надстройка над сегментной моделью. ОЗУ делится на блоки фиксированного размера, кратные степени 2, например 4 Кб. Каждый такой блок называется страницей . Основное достоинство страничного способа распределения памяти — минимально возможная фрагментация. Однако такая организация памяти не использует память достаточно эффективно за счет фиксированного размера страниц.

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

  • при использовании плоской модели памяти упрощается создание и операционной системы, и систем программирования;
  • уменьшаются расходы памяти на поддержку системных информационных структур.

В абсолютном большинстве современных 32(64)-разрядных операционных систем (для микропроцессоров Intel) используется плоская модель памяти.

Модели памяти

Директива .MODEL определяет модель памяти, используемую программой. После этой директивы в программе находятся директивы объявления сегментов ( .DATA, .STACK, .CODE, SEGMENT ). Синтаксис задания модели памяти

.MODEL модификатор МодельПамяти СоглашениеОВызовах

Параметр МодельПамяти является обязательным.

Основные модели памяти:

Модель памятиАдресация кодаАдресация данныхОпераци-
онная система
Чередование кода и данных
TINYNEARNEARMS-DOSДопустимо
SMALLNEARNEARMS-DOS, WindowsНет
MEDIUMFARNEARMS-DOS, WindowsНет
COMPACTNEARFARMS-DOS, WindowsНет
LARGEFARFARMS-DOS, WindowsНет
HUGEFARFARMS-DOS, WindowsНет
FLATNEARNEARWindows NT, Windows 2000, Windows XP, Windows VistaДопустимо

Модель tiny работает только в 16-разрядных приложениях MS-DOS. В этой модели все данные и код располагаются в одном физическом сегменте. Размер программного файла в этом случае не превышает 64 Кбайт.
Модель small поддерживает один сегмент кода и один сегмент данных. Данные и код при использовании этой модели адресуются как near (ближние).
Модель medium поддерживает несколько сегментов программного кода и один сегмент данных, при этом все ссылки в сегментах программного кода по умолчанию считаются дальними (far), а ссылки в сегменте данных — ближними (near).
Модель compact поддерживает несколько сегментов данных, в которых используется дальняя адресация данных (far), и один сегмент кода с ближней адресацией (near).
Модель large поддерживает несколько сегментов кода и несколько сегментов данных. По умолчанию все ссылки на код и данные считаются дальними (far).
Модель huge практически эквивалентна модели памяти large.

Особого внимания заслуживает модель памяти flat , которая используется только в 32-разрядных операционных системах. В ней данные и код размещены в одном 32-разрядном сегменте. Для использования в программе модели flat перед директивой .model flat следует разместить одну из директив:

Желательно указывать тот тип процессора, который используется в машине, хотя это не является обязательным требованием. Операционная система автоматически инициализирует сегментные регистры при загрузке программы, поэтому модифицировать их нужно только в случае если требуется смешивать в одной программе 16-разрядный и 32-разрядный код. Адресация данных и кода является ближней ( near ), при этом все адреса и указатели являются 32-разрядными.

Параметр модификатор используется для определения типов сегментов и может принимать значения use16 (сегменты выбранной модели используются как 16-битные) или use32 (сегменты выбранной модели используются как 32-битные).

Параметр СоглашениеОВызовах используется для определения способа передачи параметров при вызове процедуры из других языков, в том числе и языков высокого уровня (C++, Pascal). Параметр может принимать следующие значения:

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

Упрощенный формат директивы MODEL

MODEL [ ] [др. параметры]

Обязательным параметром директивы MODEL является «модель памяти». Этот параметр определяет модель сегментации памяти для программного модуля.

Возможные значения параметра «модель памяти»:

TINY — Код и данные объединены в одну группу с именем DGROUP. Используется для создания программ формата com .

SMALL — Код занимает один сегмент, данные объединены в одну группу с именем DGROUP. Эту модель обычно используют для большинства программ на языке Assembler .

MEDIUM — Код занимает несколько сегментов, по одному на каждый объединяемый программный модуль. Все ссылки на передачу управления типа far. Данные объединены в одной группе, все ссылки на них типа near.

COMPACT — Код в одном сегменте; ссылка на данные типа far.

LARGE — Код в нескольких сегментах. Каждый объединяемый в одну программу модуль хранится в отдельном сегменте кода.

Параметр «модификатор» директивы MODEL уточняет особенности использования выбранной модели памяти.

Возможные значения параметра «модификатор модели памяти»:

use16 — сегменты выбранной модели используются как 16-битные

use32 — сегменты выбранной модели используются как 32-битные

dos — программа предназначена для работы в ОС MS-DOS

Другие параметры используются при написании программ на разных языках программирования (пока использовать не будем).

Для большинства программ на ассемблере используют директиву

При использовании директивы MODEL транслятор создает и делает доступными для программиста идентификаторы, в которых хранится информация о физических адресах сегментов.

Перечислим идентификаторы, создаваемые директивой MODEL:

@code — физический адрес сегмента кода

@data — физический адрес сегмента данных типа near

@fardata — физический адрес сегмента данных типа far

@fardata? — физический адрес сегмента неинициализированных данных типа far

@curseg — физический адрес сегмента неинициализированных данных типа far

@stack — физический адрес сегмента стека

Структура программы на языке Assembler

Таким образом, общая структура программы может выглядеть следующим образом:

masm ;режим работы TASM: ideal или masm

model small ;модель памяти

.stack ;сегмент стека

.data ;сегмент данных

BEGIN : .code ;сегмент кода

end BEGIN ;конец программы с точкой входа BEGIN

Текст программы с использованием упрощенных директив сегментации.

Описаны 3 сегмента программы: сегмент данных, сегмент стека и сегмент кода.

В сегменте данных задана строка для вывода на экран.

Размер стека равен 256 байт.

Сегмент кода содержит команды начала и завершения программы, а также комментарии к пропущенным командам.

masm ;режим работы TASM: ideal или masm

model small ;модель памяти

.data ;сегмент данных

message db ‘Привет всем,$’

.stack ;сегмент стека

db 256 dup (‘?’) ;сегмент стека

.code ;сегмент кода

main : ;начало программы

mov ax,@data ;заносим в сегментный регистр ds

mov ds,ax ; физический адрес сегмента данных

;здесь будут команды вывода строки на экран

mov ax,4c00h ;пересылка 4c00h в регистр ax

int 21h ;вызов прерывания с номером 21h

end main ;конец программы с точкой входа main

Ассемблер. Сегменты памяти и регистры

Обновл. 29 Сен 2019 |

Мы уже рассматривали 3 секции из которых состоят программы на ассемблере. Эти секции также представляют различные сегменты памяти. Что интересно, если вы замените ключевое слово section на segment , то получите тот же результат. Например:

Результат выполнения программы выше:

Сегменты памяти

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

Сегмент данных (data segment) — представлен секциями .data и .bss. Секция .data используется для объявления области памяти, где хранятся элементы данных для программы. Эта секция не может быть расширена после объявления элементов данных, и она остаётся статической во всей программе. Секция .bss также является секцией статической памяти, которая содержит буферы для данных, которые будут объявлены в программе позже. Эта буферная память заполнена нулями.

Сегмент кода (code segment) — представлен секцией .text. Он определяет область в памяти, в которой хранятся коды инструкций. Это также фиксированная область.

Стек (stack) — это сегмент, который содержит значения данных, передаваемые в функции и процедуры в программе.

Регистры

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

Чтобы ускорить свою работу, процессор подключает определённые внутренние места хранения памяти, которые называются регистрами. Регистры хранят элементы данных для обработки без необходимости получать доступ к памяти. Ограниченное количество регистров встроено в чип процессора.

Регистры процессора

В архитектуре IA-32 есть десять 32-битных и шесть 16-битных процессорных регистра. Регистры делятся на три категории:

Общие регистры (General Registers)

Регистры управления (Control Registers)

Сегментные регистры (Segment Registers)

В свою очередь, общие регистры делятся на следующие:

Регистры данных (Data Registers)

Регистры-указатели (Pointer Registers)

Индексные регистры (Index Registers)

Регистры данных

Регистры данных — это четыре 32-битных регистра, которые используются для арифметических, логических и других операций. Эти 32-битные регистры могут быть использованы следующими тремя способами:

Как полные 32-битные регистры данных: EAX, EBX, ECX, EDX.

Нижние половины 32-битных регистров могут использоваться как четыре 16-битных регистра данных: AX, BX, CX и DX.

Нижняя и верхняя половины вышеупомянутых четырёх 16-битных регистров могут использоваться как восемь 8-битных регистров данных: AH, AL, BH, BL, CH, CL, DH и DL.

Некоторые из этих регистров данных имеют специфическое применение в арифметических операциях.

AX (primary accumulator) используется для ввода/вывода и в большинстве арифметических операций. Например, в операции умножения один операнд сохраняется в регистре EAX или AX или AL в соответствии с размером операнда.

BX (base register) используется при индексированной адресации.

CX (count register) хранит количество циклов в повторяющихся операциях (также, как и регистры ECX и CX).

DX (data register) используется в операциях ввода/вывода, а также с регистрами AX и DX для выполнения операций умножения и деления, связанных с большими значениями.

Регистры-указатели

Регистрами-указателями являются 32-битные регистры EIP, ESP и EBP и соответствующие им 16-битные регистры IP, SP и BP. Есть три категории регистров-указателей:

Указатель на инструкцию или команду (Instruction Pointer или IP) — 16-битный регистр IP хранит смещение адреса следующей команды, которая должна быть выполнена. IP в сочетании с регистром CS (как CS:IP) предоставляет полный адрес текущей инструкции в сегменте кода.

Указатель на стек (Stack Pointer или SP) — 16-битный регистр SP обеспечивает значение смещения в программном стеке. SP в сочетании с регистром SS (SS:SP) относится к текущей позиции данных или адреса в программном стеке.

Базовый указатель (Base Pointer или BP) — 16-битный регистр BP используется в основном при передаче параметров в подпрограммы. Адрес в регистре SS объединяется со смещением в BP, чтобы получить местоположение параметра. BP также можно комбинировать с DI и SI в качестве базового регистра для специальной адресации.

Индексные регистры

32-битные индексные регистры ESI и EDI и их 16-битные версии: SI и DI, которые используются в индексированной адресации, и, иногда, в операциях сложения/вычитания. Есть два типа индексных указателей:

Исходный индекс (Source Index или SI) — используется в качестве исходного индекса в строковых операциях.

Индекс назначения (Destination Index или DI) — используется в качестве индекса назначения в строковых операциях.

Регистры управления

Регистром управления является объединённый 32-битный регистр инструкций и 32-битный регистр флагов (регистр процессора, отражающий его текущее состояние). Многие инструкции включают в себя операции сравнения и математические вычисления, которые способны изменить состояние флагов, а некоторые другие условные инструкции проверяют значения флагов состояния, чтобы перенести поток управления в другое место.

Распространённые битовые флаги:

Флаг переполнения (Overflow Flag или OF) — указывает на переполнение старшего бита данных (крайнего левого бита) после signed арифметической операции.

Флаг направления (Direction Flag или DF) — определяет направление влево или вправо для перемещения или сравнения строковых данных. Если DF = 0 , то строковая операция принимает направление слева направо, а когда DF = 1 , то строковая операция принимает направление справа налево.

Флаг прерывания (Interrupt Flag или IF) — определяет, будут ли игнорироваться или обрабатываться внешние прерывания (например, ввод с клавиатуры и т.д.). Он отключает внешнее прерывание, когда значение равно 0, и разрешает прерывание, когда установлено значение 1.

Флаг ловушка (Trap Flag или TF) — позволяет настроить работу процессора в одношаговом режиме.

Флаг знака (Sign Flag или SF) — показывает знак результата арифметической операции. Этот флаг устанавливается в соответствии со знаком элемента данных после выполнения арифметической операции. Знак определяется по старшему левому биту. Положительный результат сбрасывает значение SF до 0, а отрицательный результат устанавливает его равным 1.

Нулевой флаг (Zero Flag или ZF) — указывает результат арифметической операции или операции сравнения. Ненулевой результат сбрасывает нулевой флаг до 0, а нулевой результат устанавливает его равным 1.

Вспомогательный флаг переноса (Auxiliary Carry Flag или AF) — после выполнения арифметической операции содержит перенос с бита 3 на бит 4. Используется для специализированной арифметики. AF устанавливается, когда 1-байтовая арифметическая операция вызывает перенос из бита 3 в бит 4.

Флаг равенства (Parity Flag или PF) — указывает общее количество 1-бит в результате, полученном после выполнения арифметической операции. Чётное число 1-бит сбрасывает PF до 0, а нечётное число 1-бит устанавливает PF равным 1.

Флаг переноса (Carry Flag или CF) — после выполнения арифметической операции содержит перенос 0 или 1 из старшего бита (крайнего слева). Кроме того, хранит содержимое последнего бита операции сдвига или поворота.

В таблице ниже указано положение битовых флагов в 16-битном регистре флагов:

Флаг:ODITSZAPC
Бит №:151413121110987654321

Сегментные регистры

Сегменты — это специфические части программы, которые содержат данные, код и стек. Есть три основных сегмента:

Сегмент кода (Code Segment или CS) — содержит все команды и инструкции, которые должны быть выполнены. 16-битный регистр сегмента кода или регистр CS хранит начальный адрес сегмента кода.

Сегмент данных (Data Segment или DS) — содержит данные, константы и рабочие области. 16-битный регистр сегмента данных или регистр DS хранит начальный адрес сегмента данных.

Сегмент стека (Stack Segment или SS) — содержит данные и возвращаемые адреса процедур или подпрограмм. Он представлен в виде структуры данных «Стек». Регистр сегмента стека или регистр SS хранит начальный адрес стека.

Кроме регистров CS, DS и SS существуют и другие регистры дополнительных сегментов (Extra Segment или ES), FS и GS, которые предоставляют дополнительные сегменты для хранения данных.

При написании программ на ассемблере, программе необходим доступ к ячейкам памяти. Все области памяти в сегменте относятся к начальному адресу сегмента. Сегмент начинается с адреса, равномерно делимого на десятичное 16 или на шестнадцатеричное 10. Таким образом, крайняя правая шестнадцатеричная цифра во всех таких адресах памяти равна 0, что обычно не сохраняется в сегментных регистрах.

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

Пример на практике

Посмотрите на следующую простую программу, чтобы понять, как используются регистры в программировании на ассемблере. Эта программа выводит 9 звездочек с простым сообщением:

Ссылка на основную публикацию
Adblock
detector