Библиотека сайта rus-linux.net
Назад | Введение в мир программирования Глава 2. Архитектура компьютера |
Вперед |
Логика работы с памятью. Машинный язык. Режимы адресации
Компьютер понятия не имеет о задаче, которую должна выполнить ваша программа. Он просто делает то, что вы ему говорите. Например, если вы совершите опечатку и введёте несуществующий ASCII-код символа, компьютер обязательно попытается его обработать (вывести на экран или записать в память).
Стандартным средством, благодаря которому компьютер узнаёт о том, что из себя представляют числа в памяти (являются ли они командами, которые следует исполнить), служит регистр команд, содержащий указатель на адрес, где должны быть размещены команды.
Если вы скажете компьютеру начать выполнять команды, размещённые по ошибочному адресу, он не раздумывая будет пробовать это сделать, что может привести к порче информации и сбою в работе программы.
Таким образом, программируя (особенно если речь идёт о языке низкого уровня, таком как ассемблер) вы должны хорошо представлять как данные размещены в памяти компьютера. Как будет наглядно показано в следующей главе (Представление информации с помощью чисел), буквы, картинки, музыка, веб-страницы, текстовые документы представляют из себя не более, чем длинные последовательности чисел, которые интерпретируются программами.
Мы уже говорили, что ассемблер является упрощённым вариантом машинного языка, то есть вместо кодов операций он содержит несколько мнемонических команд, использование которых облегчает процесс программирования.
Машинный язык
также называют системой команд
, или архитектурой
набора команд
(Instruction Set Architecture).
Читатель, вероятно, встречал такие аббревиатуры как RISC
и CISC
.
RISC --- это архитектура компьютера с ограниченным/сокращённым набором команд
(Restricted/Reduced Instruction Set Computer). Аббревиатура CISC расшифровывается как
"компьютер со сложным набором команд" (Complex Instruction Set Computer).
Например, процессоры x86
относятся к семейству CISC, а процессоры
MIPS
- к семейству RISC. Существуют также архитектуры VLIW
(Very Long Instruction Word), EPIC
(Explicitly Parallel Instruction Computing),
MISC
(Minimal Instruction Set Computer), OISC
(One Instruction Set Computer).
Команды, исполняемые компьютером могут быть записаны в безадресном (операнд включён в код команды), одноадресном, двухадресном и трёхадресном формате. Иными словами, адреса бывают явными (одно-, двух- и трёхадресный формат) или неявными (безадресный формат).
Операндом
в рассматриваемом контексте могут являться:
- данные, которые явно либо неявно задаются машинной командой и которые должны быть обработаны либо выработаны в ходе исполнения машинной команды;
- явная ссылка в машинной команде на такие данные;
- место, где находятся или должны быть помещены такие данные: позиции в оперативной, внешней, внутренней или управляющей памяти, общие и специальные регистры, флаги, поля признаков, входы и выходы управляющих сигналов.
Процесс (способ) установления соответствия между множеством однотипных
объектов в вычислительной системе и множеством их адресов называется адресацией
.
Иными словами, с помощью адресации определяются адреса размещения операндов в памяти
компьютера.
Перечислим режимы адресации, которые чаще всего используются при программировании компьютеров семейства Intel x86, а также могут быть применены на платформе MIPS. Читатель должен понимать, что предлагаемый список доступных режимов требует уточнения в зависимости от того какова архитектура целевой вычислительной системы.
В непосредственном
режиме адресации (immediate addressing mode)
сведения, необходимые для доступа к данным включаются в команду процессора.
К примеру, если мы хотим инициализировать регистр, поместив туда нуль
,
разумнее всего будет не указывать адрес, откуда можно прочитать 0
,
а использовать непосредственный режим адресации, указав 0
в качестве
операнда команды.
Иными словами, при непосредственной адресации, значение в формате байта,
слова или двойного слова (машинное слово
--- это количество данных,
которое процессор может обработать за одну операцию) передаётся в
регистр-приёмник или в память. Обычно машинное слово по длине равно размеру
регистра общего назначения процессора. На рынке широко доступны процессоры,
оперирующие словами по 4 байта (x86-32, MIPS32) и по 8 байт (x86-64, MIPS64).
Непосредственный операнд может быть задан в различных системах счисления (шестнадцатеричной, двоичной, десятичной). Символы ASCII непосредственно задаются числовым кодом или буквой в кавычках.
В режиме регистровой адресации
(register addressing mode)
команда содержит имя регистра, в котором хранятся числа для обработки.
Копия байта, слова или двойного слова из регистра-источника передаётся в регистр-приёмник.
Размерность регистров источника и приёмника должна быть одинаковой.
Прямой режим адресации
(direct addressing mode) подразумевает указание
адреса памяти в качестве операнда команды (адрес данных в памяти образуется
совокупностью значения, содержащегося в сегментном регистре и смещения,
заданного в команде). Данные пересылаются между памятью и регистром.
К примеру, можно сказать: "Компьютер, загрузи, пожалуйста, в регистр данные,
содержащиеся в памяти по адресу 2002.". Среагировав на наши слова, компьютер
перейдёт к байту номер 2002 и скопирует его содержимое в нужный регистр.
В режиме индексной адресации
(indexed addressing mode) команда
содержит в качестве операнда базовый адрес, а также имя индексного регистра,
содержащего значение смещения от базового адреса.
К примеру, если базовый адрес равен 2002, а смещение равно 4,
то адрес, по которому обратиться команда будет равен 2006.
С помощью индексной адресации можно организовывать циклы, в которых происходит последовательное обращение к ячейкам памяти, имеющим адрес, находящийся с разным смещением от базового адреса (базово-индексная адресация).
Процессоры x86 поддерживают использование множителя (multiplier)
,
записываемого в индексный регистр (индексная адресация с масштабированием).
Это позволяет получать доступ к участкам памяти по байту или по машинному
слову за один проход цикла, а также переходить к нужному участку памяти.
Приведём примеры программ (c использованием режимов адресации) для процессоров Intel x86 и MIPS.
Программа для as (процессор x86)
.section .data .section .text .globl _start _start: # Воспользуемся непосредственной адресацией для указания того, # что программа будет осуществлять запись в стандартное # устройство ввода-вывода. Логика работы Linux подразумевает, # что цифра четыре в регистре eax говорит компьютеру произвести # запись по адресу файлового дескриптора (он находится в регистре ebx). # Цифра один в регистре ebx сообщает ядру, что запись будет # осуществлена на стандартное устройство вывода (обычно - это экран # терминала). Согласно стандарту POSIX цифра 1 соответствует # стандартному устройству вывода (stdout). movl $4, %eax movl $1, %ebx # Прямая адресация. Согласно логике работы ядра, в регистр ecx должна быть # помещена переменная, содержащая текст, который надо записать в стандартное # устройство вывода. В нашей программе этот текст хранится по адресу переменной # $text. movl $text, %ecx # Далее, согласно логике работы Linux (ядра операционной системы GNU/Linux), # в регистр edx необходимо занести длину печатаемого сообщения (число байт, # которое оно занимает в памяти). Учитывая, что мы решили вывести на экран # надпись на русском языке в кодировке UTF-8, каждый из кириллических символов # требует по два байта для хранения. В свою очередь, пробел, восклицательный # знак и символ новой строки занимают по одному байту. Отсюда # получаем: (10 кириллических символов * 2) + 5 = 25 байт. movl $25, %edx # Теперь можно осуществить системный вызов, то есть обращение # за помощью к ядру операционной системы. int $0x80 # Завершение работы программы также требует занесения в регистры служебной # информации. В частности, в eax должна быть единица (соответствует выходу # из программы), а в ebx должен быть внесён код завершения (возврата). Обычно # успешному завершению соответствует код возврата равный нулю, а единица в # коде возврата сообщает об ошибке. movl $1, %eax # Для разнообразия, прибегнув к регистровой адресации, # внесём код возврата, равный единице. movl %eax, %ebx # Снова выполним системный вызов 0x80. int $0x80 text: .ascii "Всем привет!!!\n"
Теперь произведём компиляцию и компоновку нашей новой программы, приветствующей всех.
as hello.s -o hello.o ld hello.o -o hello ./hello
Убедиться в том, что код возврата нашей программы равен единице можно выполнив (сразу после завершения работы программы hello) в терминале следующую команду.
echo $?
Любопытные читатели найдут подробную информацию о логике работы системных вызовов Linux на сайте syscalls.kernelgrok.com.
Теперь обсудим адресацию памяти в контексте особенностей процессоров MIPS. Напомним, что MIPS --- это представитель архитектуры с сокращённым набором команд (RISC).
Представленная ниже программа для spim
(процессор MIPS, эмулируемый программно)
иллюстрирует один из вариантов использования временных регистров (temporary registers)
$t0
и $t1
. Сначала в регистр $t1
загружается единица (непосредственная адресация),
потом к единице прибавляется число два и результат записывается в регистр $t0
.
main: li $t1, 1 # непосредственная адресация add $t0, $t1, 2 # трёхадресный формат команды li $v0, 10 syscall
По инструкции syscall
выполняется тот или иной системный вызов. Какой именно
--- зависит от содержимого регистров. Страница MIPS System Calls подробно рассказывает об этом. В частности,
наличие в регистре $v0
числа 4
соответствует выводу на печать строки. Если
же в $v0
записать число 10
, будет выполнен системный вызов, ответственный за
выход из программы.
spim
является эмулятором процессора MIPS32. Сохранив приведённый выше фрагмент кода
в файле с именем mips32addr.asm
его можно загрузить в эмулятор
и проверить содержимое нужных регистров.
# spim load "mips32addr.asm" run print $t0
Для наглядности приведём пример программы на языке ассемблера MIPS, печатающей фразу "Доброе утро!".
.text main: la $a0, thetext # прямая адресация li $v0, 4 # непосредственная адресация syscall li $v0, 10 syscall .data thetext: .asciiz "Доброе утро!\n"
Как видно, исходный код программы, представленной выше содержит две секции:
.text
и .data
. В .text
размещаются инструкции, которые
нельзя изменить в ходе выполнения программы. Секция .data
содержит
записи, которые линкёр (компоновщик) может занести в память перед
тем как программа будет исполнена.
MIPS поддерживает три формата команд: регистровый (Register type, R-type), непосредственный (Immediate, I-type) и формат перехода (Jump type, J-type). В рамках одного и того же формата доступно использование различных режимов адресации. Напомним, что под режимом адресации понимается метод определения адреса хранения нужной информации.
В документации о режимах адресации MIPS часто используются следующие обозначения:
op (operation code)
- код операции (6 бит)rs (source register)
- регистр-источник (5 бит)rd (destination register)
- регистр-приёмник (5 бит)rt (target register or branch condition)
- целевой регистр или условие перехода (5 бит)immediate
- непосредственное смещение перехода или адреса (16 бит)target
- цель перехода (26 бит)shamt (shift amount)
- размер сдвига (5 бит)funct (function field)
- поле функции (6 бит)
Ассемблер MIPS поддерживает несколько способов работы с операндами при адресации (подробнее см. [Ellard1994, 66]):
(регистр)
- обращение к содержимому регистра;константа
- постоянный адрес в числовой форме;константа(регистр)
- сумма постоянного адреса и содержимого регистра;символ
- адрес размещения символа;символ + константа
- адрес символа + постоянный адрес в числовой форме;символ + константа(регистр)
- адрес символа + постоянный адрес в числовой форме + содержимое регистра.
На этом пока что прекратим описание ассемблера и архитектуры MIPS. Так или иначе, мы уже достаточно детально, с использованием примеров для разных архитектур ЭВМ, рассмотрели логику работы компьютера с памятью, а также некоторые особенности машинных языков и режимов адресации.
Литература для самообразования
- Касперски К. Архитектура x86-64 под скальпелем ассемблерщика. URL: http://www.insidepro.com/kk/072/072r.shtml (дата обращения: 29.09.2012).
- Мазонка О. Копирование Бита - Простейшая Вычислительная Машина. URL: http://www.opennet.ru/docs/RUS/bbjr/bbjr.utf8 (дата обращения: 29.10.2012).
- Озеров С. Архитектура процессоров. MIPS, Sparc, ARM и PowerPC. URL: http://www.computerra.ru/terralab/platform/235565/ (дата обращения: 04.11.2012).
- Gilreath W. F., Laplante P. A. Computer Architecture: A Minimalist Perspective. URL: http://cn.ccebook.org/preview/1402074166/Computer-Architecture-A-Minimalist-Perspective-The-Springer-International-Series (дата обращения: 20.11.2012).
- Ellard D. J. MIPS Assembly Language Programming. CS50 Discussion and Project Book. URL: http://ellard.org/dan/www/Courses/cs50-asm.pdf (дата обращения: 21.08.2012).
- Hennessy J., Jouppi N., Przybylski S., Rowen C., Gross T., Baskett F., Gill J. MIPS: A Microprocessor Architecture. Departments of Electrical Engineering and Computer Science. Stanford Univresity.
- Larus J. R. SPIM S20: A MIPS R2000 Simulator `` 1÷25th the performance at none of the cost''. URL: http://www.doc.ic.ac.uk/lab/secondyear/spim/ (дата обращения: 05.11.2012).
- Miller K. S. MIPS architecture. URL: http://pages.cs.wisc.edu/~smoler/x86text/lect.notes/MIPS.html (дата обращения: 05.11.2012).
- MIPS Architecture and Assembly Language Overview. URL: http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm (дата обращения: 04.11.2012).
- MIPS Assembly Language Programmer's Guide. URL: http://www.tik.ee.ethz.ch/education/lectures/TI1/materials/assemblylanguageprogdoc.pdf (дата обращения: 04.11.2012).
- MIPS System Calls. URL: https://www.student.cs.uwaterloo.ca/~isg/res/mips/traps (дата обращения: 04.11.2012).
Предыдущий раздел: | Оглавление | Следующий раздел: |
Представление двоичных чисел в компьютере | Представление информации с помощью чисел |