Каждая уважающая себя программа на ассемблере MIPS должна содержать директивы, т.е. блоки данных. К примеру, все переменные и константы следует объявить в директиве .data (директивы начинаются с точки). Заметьте, что значения в регистрах не относятся к «все переменные и константы», их вообще так не следует называть во избежание путаницы. Рассмотрим простейшую программу на ассемблере, вычисляющую факториал числа 7 (можно заменить на другое):
.data #Это комментарий string1: .asciiz «! = » #строковое ASCII значение с нулевым символом string2: .asciiz «n» .text #Тут блок с программой main: #aka main() в C li $t1, 1 li $t2, 1 j loop loop: #Метка для перехода, здесь служит для реализации цикла mult $t1,$t2 mflo $t1 nop nop addiu $t2,$t2,1 bgt $t2, 7, endloop j loop endloop: subiu $t2,$t2,1 li $v0, 1 la $a0, ($t2) syscall #Очень важная инструкция, будет рассмотрена ниже la $a0, string1 li $v0, 4 syscall li $v0, 1 la $a0, ($t1) syscall la $a0, string2 li $v0, 4 syscall li $v0, 10 syscall
Формат инструкций [ ]
Существуют, помимо «настоящих» аппаратных инструкций процессора, и псевдоинструкции, которые транслируются в «настоящие» после компиляции. Инструкции делятся на 3 типа: R,I и J. В данной таблице рассмотрен формат каждой инструкции:
FASM. Установка FASM. Структура программы на ассемблере. Урок 1
- Address — Адрес в программе, т.е. куда «прыгать».
- RX,RY,RZ — Некие регистры
- Shamt — Область размера сдвига регистра
- Function — Область функции
- Immediate — Некое значение
Регистры [ ]
Чтобы обратиться к регистру, нужно его как-то «выделить». Если в x86 регистры выделяются значком процента, например так: %eax (ATплавающие» операции рассмотрим позже.
И да, назначения регистров — всего лишь соглашение, можно использовать и по своему. Только потом не удивляйтесь, почему ваш код никто не понимает.
$0 | $zero | Всегда содержит нолик. Очень полезен. |
$1 | $at | Временный регистр для ассемблера. |
$2,$3 | $v0,$v1 | Возвращаемые значения подпрограмм. |
$4-$7 | $a0-$3 | Аргументы подпрограмм. |
$8-$15 | $t0-$t7 | Временные данные |
$16-$23 | $s0-$s7 | Сохраненные данные |
$24,$25 | $t8,$t9 | Временные данные |
$26,$27 | $k0,$k1 | Используются ядром ОС |
$28 | $gp | Глобальный указатель |
$29 | $sp | Указатель на вершину стека |
$30 | $fp | Указатель на фрейм |
$31 | $ra | Возвращаемый адрес |
WARNING: Существуют также регистры HI и LO, служащие для хранения результатов операций умножения и деления. Так вот, никогда не используйте их как регистры для выполнения различных арифметических и логических операций, MIPS такого не предусмотрел.
Арифметические инструкции [ ]
Здесь не рассмотрены псевдоинструкции, возможно, они когда нибудь появятся позже.
$x,$y,$z — регистры, C — целое значение
x = z+y ,генерирует прерывание при переполнении
WARNING: Никогда не используйте инструкции умножения и деления сразу после инструкций mfhi и mflo! Это связано с аппаратным устройством конвеера MIPS, игнорирование данного правила может повлечь за собой неопределенное поведение самого процессора. В эмуляторах, данным правилом можно пренебречь.
Источник: osdev.fandom.com
Структура программы на языке ассемблер
При выполнении программы, микропроцессор взаимодействует с оперативной памятью, где хранятся исполняемая программа и данные, а так же с периферийными устройствами.
Программируемая структура процессора
Для организации вычислений микропроцессор i8086 имеет в своём составе 14 шестнадцатиразрядных регистров, которые обеспечивают выполнение программы:
Регистры общего назначения | Сегментные регистры | Специальные регистры | |||
AH | AL | AX | CS | SP | Указатель стека |
BH | BL | BX | DS | BP | Указатель базы стека |
CH | CL | CX | ES | IP | Указатель инструкций |
DH | DL | DX | SS | FLAGS | Регистр флагов |
SI | |||||
DI |
Регистры общего назначения:
AX(AH, AL), BX(BH, BL), CX(CH, CL), DX(DH, DL) делятся программно на пары однобайтных регистров и могут использоваться для хранения данных. Разбиение на однобайтные регистры позволяет увеличить общее число регистров;
SP, BP – указатель и база стека, соответственно, обеспечивают доступ к данным в стеке, могут использоваться для хранения данных, но делать это не рекомендуется, так как при этом возможно нарушение адресации в стеке, особенно при использовании SP.
SI, DI – шестнадцатиразрядные регистры для хранения данных.
CS, DS, ES, SS – хранят адреса сегментов в памяти, не могут использоваться для хранения данных.
IP – регистр инструкций – хранит адрес (смещение) следующей исполняемой команды.
FLAGS – регистр флагов содержит набор битовых флагов, определяющий текущее состояние процессора и результат выполнения предыдущей команды (таблица 2.1).
Таблица 2.1 | ||
Регистр флагов процессора | ||
Флаг | Название | Назначение |
О | Переполнение | Переполнение при выполнении арифметических операций |
D | Направление | Направление пересылки данных при выполнении строковых команд |
I | Прерывание | Разрешает/Запрещает внешние прерывания |
T | Пошаговый режим | Останов после выполнения каждой команды(используется отладчиками) |
S | Знак | Знак результата выполненной команды(0 – плюс, 1 – минус) |
Z | Ноль | Значение результата выполненной команды(0 – ненулевой, 1 – нулевой) |
A | Внешний перенос | Используется для специальных арифметических операций |
P | Контроль чётности | Число единиц в операнде(0 – нечётное, 1 – нечётное) |
C | Перенос | Содержит перенос из старшего бита при выполнении арифметических операциях |
Память, с которой взаимодействует процессор при обработке программ, называется Оперативным Запоминающим Устройством (ОЗУ) или Random Access Memory (RAM). Она состоит из набора однобайтных ячеек, обращение к которым происходит по их номерам (физическим адресам). Число ячеек зависит от ширины шины адреса и составляет для процессора i8086 (ширина шины адреса равна 20) 220 – ячеек (1Мбайт). Для современных процессоров с шириной шины адреса 32 объём ОЗУ может доходить до 4 Гбайт.
Данные можно читать или сохранять в ОЗУ байтами, указывая номер требуемой ячейки или словами (2 байта), указывая адрес младшей ячейки памяти и вводя специальный префикс.
Для обращения к памяти процессор предварительно помещает адрес ячейки в один из своих регистров, но для процессора i8086, очевидно нельзя в шестнадцатиразрядном регистре хранить двадцатиразрядный адрес. Поэтому применяют так называемую сегментацию памяти, которая заключается в том, что истинный, физический адрес ячейки хранится в двух регистрах.
Один из них – сегментный, он хранит адрес начала блока памяти, который и называется сегментом. Если к шестнадцати разрядам сегмента мысленно справа дописать четыре двоичных нуля(16+4=20), то получим физический адрес начала сегмента в ОЗУ. Второй регистр хранит величину смещения адреса требуемой ячейки от начала сегмента. Адрес ячейки памяти записывается в виде двойного слова (4 байта): :.
Сегмент всегда начинается с ячейки, номер которой заканчивается на 4 двоичных (или один шестнадцатеричный) нуля. Минимальная длина сегмента 16 байтов (параграф). Максимальная длина определяется длиной регистра, хранящего смещение и равна 216(64 Кбайта).
Пара регистров CS:IP(:) определяют адрес следующей команды программы.
Для адресации данных используются сегментные регистры DS и ES, а в качестве регистров, хранящих смещение, используются регистры общего назначения BX, SI, DI. Для работы с сегментом стека используют сегментный регистр SS и регистр BP.
Структура программы на языке Ассемблер
Программа на языке ассемблера представляет собой текст разбитый на строки. Каждая строка либо соответствует машинной команде, либо является директивой ассемблера или макрокомандой. Команды и директивы можно набирать как большими, так и малыми латинскими буквами. Русские буквы можно использовать только в комментариях.
команды или директивы
команды или директивы
Директива endотмечает конец текста программы и указывает ассемблеру, где завершить трансляцию. Поэтому директива endдолжна присутствовать в каждой программе.
указывает инструкцию, с которой должно начинаться выполнение программы.
Каждая программа содержит сегменты данных и команд, но минимально должна содержать сегмент команд.
Строка программы, в общем случае, состоит из четырех полей:
Поле метки | Поле операции | Поле операндов | Поле комментария |
M1: | Add | AX, BX | ; сложение |
Имена данных, процедур, сегментов или метки команд могут состоять не более чем из 31 латинских букв и цифр, причем первым символом должна быть обязательно буква. Большие и маленькие буквы не различаются.
Директивой называется команда транслятору для выполнения определённых данной директивой действий, сама директива в текст транслированной программы не включается.
1. Директива задания исходных данных:
- — имя массива данных, по которому к ним можно обратиться из команды;
- d(define)– определяет начало массива данных;
- — размер констант, входящих в массив:
- — числовой или символьный элемент массива данных.
В ассемблере используется несколько типов констант:
десятичные – последовательность цифр от 0 до 9;
шестнадцатеричные – последовательность шестнадцатеричных цифр от 0 до 9 и от А или а до F или f завершающаяся буквой H или h, первой должна быть десятичная цифра или 0;
восьмеричные – последовательность цифр от 0 до 7, завершающаяся буквами Q или q;
двоичные – последовательность цифр от 0 до 1, завершающаяся буквой B или b;
символьные – символ или группа символов, заключённые в кавычки;
знак ? – используется для резервирования места для данных.
data1 db 123, 0a2h, 75q, 110011b, ‘a’, ‘пример’, ?, ?
Для заполнения больших массивов используется директива dup (duplicate):
— задаёт количество размещаемых в памяти данных, определяемых образцом;
— любая допустимая группа констант.
data2 db 23 dup(1, 2, ‘x’)
выделяет в памяти 23 · 3=69 байтов и заносит в них образец 1, 2, ‘x’, 1, 2, ‘x’, … .
2. Директива использования сегментных регистров по умолчанию:
Как отмечалось выше, для задания адреса в памяти требуется два регистра, один из них всегда сегментный, поэтому в команде при обращении к памяти приходится набирать имя сегментного регистра, часто одного и того же. Директива assumeпозволяет избежать этого. Транслятор сопоставляет имя массива данных и автоматически подставляет сегментный регистр, заданный для сегмента, в котором расположен данный массив. Слово nothingпоказывает, что данный сегментный регистр не адресуется по умолчанию. Директива assume может использоваться в программе при каждом изменении сегмента для данного сегментного регистра, но обязательно в начале сегмента, где она задаёт по умолчанию сегментный регистр для сегмента кодов.
assumecs:code, ds:data1, es:nothing
Здесь code и data1 – имена сегментов кодов и данных, соответственно.
1. Регистровая прямая — операнд находится в регистре.
— АХ, ВХ, СХ, DX, SI, DI, BP, SP, AL, BL, СL, DL, AH, BH, CH, DH.
mov АХ,SI ; переслать содержимое регистра SI в регистр АХ.
2. Непосредственная -непосредственный операнд (константа) присутствует в команде.
mov AX, 093Ah ; занести константу 093Ah в регистр АХ.
3. Прямая — исполнительный адрес операнда присутствует в команде.
mov AX, WW ; переслать в АХ слово памяти с именем WW
mov BX, WW+2 ; переслать в ВХ слово памяти отстоящее от переменной с именем WW на 2 байта.
4. Регистровая косвенная — регистр содержит адрес операнда.
mov [ BX ], CL ; переслать содержимое регистра CL по адресу, находящемуся в регистре ВХ.
5. Регистровая относительная — адрес операнда вычисляется как сумма содержимого регистра и смещения.
— SI или DI индексная адресация, ВХ или ВР — базовая адресация.
mov АХ, WW[SI] ; переслать в АХ слово из памяти, адрес которого вычисляется как сумма содержимого регистра SI и смещения WW.
6. Индексно — базовая — адрес операнда вычисляется как сумма содержимых базового и индексного регистров и смещения.
Обозначение — [][] или [][] или [][] константное выражение,
где- SI или DI,- ВХ или ВР.
mov [BX+ SI+ 2], CL; переслать содержимое регистра CL по адресу, вычисляемому как сумма содержимого регистров ВХ, SI и константы 2.
Статьи к прочтению:
- Структура программных продуктов
- Структура современной информатики
Как написать программу на Assembler часть 1
Похожие статьи:
- Структура программы на языке pascal Введение Под языком программирования мы будем понимать совокупность средств и правил представления алгоритма в виде, приемлемом для компьютера….
- Структура программы на языке си Программа на языке Си определяется как совокупность одного или нескольких модулей. Модулем является самостоятельно компилируемый файл. Модуль содержит…
Источник: csaa.ru
Структура программы на языке ассемблер
Программирование на уровне машинных команд — это тот минимальный уровень, на котором возможно составление программ. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре вычислительной машины.
Каждая машинная команда состоит из двух частей:
Машинная команда микропроцессора, записанная на языке ассемблера, представляет собой одну строку, имеющую следующий синтакический вид:
метка команда/директива операнд(ы) ;комментарии
При этом обязательным полем в строке является команда или директива.
Метка, команда/директива и операнды (если имеются) разделяются по крайней мере одним символом пробела или табуляции.
Если команду или директиву необходимо продолжить на следующей строке, то используется символ обратный слеш: .
По умолчанию язык ассемблера не различает заглавные и строчные буквы в написании команд или директив.
Примеры строк кода:
Метки
Метка в языке ассемблера может содержать следующие символы:
В качестве первого символа метки может использоваться точка, но некоторые компиляторы не рекомендуют применять этот знак. В качестве меток нельзя использовать зарезервированные имена Ассемблера (директивы, операторы, имена команд).
Команды
Команда указывает транслятору, какое действие должен выполнить микропроцессор. В сегменте данных команда (или директива) определяет поле, рабочую область или константу. В сегменте кода команда определяет действие, например, пересылка (mov) или сложение (add).
Директивы
Ассемблер имеет ряд операторов, которые позволяют управлять процессом ассемблирования и формирования листинга. Эти операторы называются директивами . Они действуют только в процессе ассемблирования программы и, в отличие от команд, не генерируют машинных кодов.
Операнды
Операнд – объект, над которым выполняется машинная команда или оператор языка программирования.
Команда может иметь один или два операнда, или вообще не иметь операндов. Число операндов неявно задается кодом команды.
Примеры:
Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Однако рекомендуется записывать их в колонку для большего удобства чтения программы.
В качестве операндов могут выступать
Идентификаторы
Идентификаторы – последовательности допустимых символов, использующиеся для обозначения таких объектов программы, как коды операций, имена переменных и названия меток.
Правила записи идентификаторов.
Комментарии
Структура программы на ассемблере
Пример «ничего не делающей» программы на языке ассемблера:
Структура программы на языке ассемблера.
Исходный текст программы разделяется на следующие секции:
Секция данных содержит данные, доступные для чтения и записи. Вся секция данных включается в exe-файл и может быть инициализирована данными.
Неинициализированные данные не имеют никакого содержания при запуске, и даже не включены в exe-файл непосредственно, это только часть памяти, зарезервированной Windows. Эта секция доступна для чтения и записи.
Кроме того, в первом случае при загрузке программы из винчестера в оперативной памяти сразу же автоматически будет отведено место под байт. Во втором случае при загрузке операционной системе придется помимо места под программу выделять место под байт.
.DATA | .DATA? | |
+ | Быстрая загрузка | Маленький объем исполняемого модуля |
— | Большой объем исполняемого модуля | Медленная загрузка |
Секция констант аналогична секции данных, но доступна только для чтения (проще и быстрее объявлять константы в файлах для включения, и использовать их как непосредственные значения – то есть создаются файлы с расширением “*.inc”, в которых определяются имена и значения констант, которые могут быть использованы в алгоритме основной программы).
Секция кода содержит текст программы на языке ассемблера, реализующий требуемый алгоритм работы.
У вас представлен шаблон программы на языке ассемблера.
.MODEL Flat, STDCALL
Проанализируем особенности этого шаблона.
Директива – указания компилятору на выполнение некоторых действий или служат для задания режима его работы. У директив нет аналогов среди машинных команд.
1) Директивы установки типа процессора – это директивы, которые определяют минимально возможный тип применяемого процессора (то есть на каком процессоре сможет работать данная программа, при этом программы для ранних моделей процессора будут работать с процессорами более поздних моделей)
Данная директива указывает ассемблеру использовать набор команд для процессора 80386. Директивы установки типа процессора приведены в таблице 1.
Директива | Описание |
.8086 | Допустимы команды для процессоров 8086 и 8088. Команды для процессоров 80186 и более поздних не используются. Команды для 8087 разрешены. |
.186 | Разрешены команды для процессора 80186, команды для последующих процессоров не используются. |
.286 | Доступны команды для 80286, команды для более поздних процессоров не используются. |
.386 | Доступны команды для 80386, команды для более поздних процессоров не используются |
.486 | Доступны команды для 80486, команды для процессоров Pentium не используются |
.586 | Доступны команды для процессоров 80286, команды для более поздних процессоров Pentium. |
.287 | Используются команды вычислений с плавающей запятой для математического сопроцессора 80287. |
.387 | Используются команды вычислений с плавающей запятой для математического сопроцессора 80387. |
.686 | Доступны команды для процессоров Pentium Pro. |
Таблица 1. Директивы установки типа процессора.
2) Директивы выбора модели памяти.
.MODEL FLAT, STDCALL
В таблице 2 представлены модели памяти, используемые в MASM.
Модель | Описание |
Tiny (тонкая) | Коды и данные вместе должны занимать не более 64 Кбайт. |
Small (малая) | Код 64 Кбайт, данные > 64 Кбайт. Много сегментов кодов и данных. |
Huge (огромная) | Аналогична модели Large, за исключением того, что отдельные переменные, такие как массив, могут быть больше 64 Kбайт. |
Flat (плоская) | Нет сегментов, 32-разрядная адресация используется как для кодов, так и для данных. |
Таблица 2. Модели памяти, используемые в MASM
При разработке программ для Windows используется только плоская модель памяти (FLAT).
Ключевое слово STDCALL устанавливает порядок передачи параметров при вызове подпрограмм и функций справа налево.
Самый пpавый паpаметp первым помещается в стек. Пусть есть функция, которая использует три параметра : f(p1, p2, p3), которая описана в тексте исходной программы. При вызове функции с именем f(p1, p2, p3) ассемблерный код будет выглядеть так:
push p3 ; Поместить в стек тpетий паpаметp
push p1 ; И, наконец, первый параметр
Эта функция для своей работы берет параметры из стека: сначала первый, потом второй и затем третий
3) Директивы, определяющие начала секций программы.
Все четыре директивы определяют начало секций программы. В плоской модели памяти, используемой в Windows, нет сегментов, но для удобства виртуальное адресное пространство делится на логические секции. Hачало одной секции отмечает конец предыдущей. Есть две группы секций:
Программист не обязан задействовать все тpи секции. Необходимо объявлять только те, которые будут использоваться.
Начало секции кода должно начинаться с непрерывной (без пробелов) строки, которая заканчивается символом двоеточия “:”. Эта строка с двоеточием называется меткой точки входа в программу. В конце секции кода пишется служебное слова “end”, после которого указывается эта же метка, то есть обе метки должны быть идентичны. Вся программа на языке ассемблера должна располагаться между точкой входа и точкой выхода, определяемой служебным словом “end” с меткой, соответствующей точке входа.
1. Структура программы на ассемблере
1. Структура программы на ассемблере
Программа на ассемблере представляет собой совокупность блоков памяти, называемых сегментами памяти. Программа может состоять из одного или нескольких таких блоков-сегментов. Каждый сегмент содержит совокупность предложений языка, каждое из которых занимает отдельную строку кода программы.
Предложения ассемблера бывают четырех типов:
1) команды или инструкции, представляющие собой символические аналоги машинных команд. В процессе трансляции инструкции ассемблера преобразуются в соответствующие команды системы команд микропроцессора;
2) макрокоманды. Это оформляемые определенным образом предложения текста программы, замещаемые во время трансляции другими предложениями;
3) директивы, являющиеся указанием транслятору ассемблера на выполнение некоторых действий. У директив нет аналогов в машинном представлении;
4) строки комментариев, содержащие любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.