Ассемблер. Системные вызовы и режимы адресации

  Светлана Деменева  | 

  Обновл. 4 Окт 2019  | 

 1146

Системные вызовы — это программные интерфейсы между пользователем и ядром. Мы уже использовали следующие системные вызовы:

   sys_write — для вывода на экран;

   sys_exit — для выхода из программы.

Системные вызовы Linux

В своих программах на ассемблере вы можете использовать системные вызовы Linux. Для этого нужно:

   поместить номер системного вызова в регистр EAX;

   сохранить аргументы системного вызова в регистрах EBX, ECX и т.д.;

   вызвать соответствующее прерывание (80h);

   результат обычно возвращается в регистр EAX.

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

   EBX

   ECX

   EDX

   ESI

   EDI

   EBP

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

В следующем примере мы будем использовать системный вызов sys_exit:

А в следующем — sys_write:

Все системные вызовы перечислены в /usr/include/asm/unistd.h вместе с их номерами (значение, которое помещается в EAX перед вызовом int 80h).

В следующей таблице приведены некоторые системные вызовы, которые мы будем использовать:

%eax Название %ebx %ecx %edx %esx %edi
1 sys_exit int
2 sys_fork struct pt_regs
3 sys_read unsigned int char * size_t
4 sys_write unsigned int const char * size_t
5 sys_open const char * int int
6 sys_close unsigned int

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

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

Please enter a number:
1234
You have entered:1234

Режимы адресации


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

Есть три основных режима адресации:

   Регистровая адресация

   Прямая (или ещё «непосредственная») адресация

   Адресация памяти

Регистровая адресация

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

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

Прямая (непосредственная) адресация


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

Адресация памяти

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

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

При прямой адресации памяти один из операндов ссылается на ячейку памяти, а другой — на регистр. Например:

Адресация прямого смещения


Этот режим адресации использует арифметические операторы для изменения адреса. Например, следующие определения определяют таблицы данных:

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

Непрямая адресация памяти

Обычно для этой цели используются базовые регистры EBX, EBP (или BX, BP) и индексные регистры (DI, SI), используемые в квадратных скобках для ссылок на память.

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

В следующем примере мы получаем доступ к разным элементам переменной:

Инструкция MOV


Мы уже использовали инструкцию MOV для перемещения данных из одного пространства хранения в другое. Инструкция MOV принимает два операнда.

Синтаксис инструкции MOV:

Инструкция MOV может иметь одну из следующих пяти форм:

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

Не ясно, хотите ли вы переместить байтовый или словесный эквивалент числа 110. В таких случаях целесообразно использовать спецификатор типа.

В следующей таблице приведены некоторые из общих спецификаторов типов:

Тип спецификатора Байт
BYTE 1
WORD 2
DWORD 4
QWORD 8
TBYTE 10

Следующая программа иллюстрирует некоторые из концепций, которые обсуждались выше: в секции данных памяти сохраняется имя Zara Ali, затем оно программным образом изменяется на Nuha Ali и выводятся уже оба имени.

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

Zara Ali Nuha Ali

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (3 оценок, среднее: 3,00 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *

telegram канал
НОВОСТИ RAVESLI