Ассемблер — это просто хадкорный ассемблер

             

Философия ассемблера


Ассемблер— это низкоуровневый язык, оперирующий машинными понятиями и концепциями. Не ищите команду вывода строки "hello, world!". Здесь ее нет. Вот кратный перечень действий, которые может выполнить процессор: сложить/вычесть/разделить/умножить/сравнить два числа и в зависимости от полученного результата передать управление на ту или иную ветку, переслать число с одного места в другое, записать число в порт или прочитать его оттуда. Управление периферией осуществляется именно через порты или через специальную область памяти (например, видеопамять). Чтобы вывести символ на терминал, необходимо обратиться к технической документации на видеокарту, а чтобы прочитать сектор с диска — к документации по накопителю. К счастью, эту часть работы берут на себя драйвера и выполнять ее вручную обычно не требуется (к тому же, в нормальных операционных системах, таких, например, как Windows NT с прикладного уровня порты недоступны).

Другой машинной концепцией является регистр. Объяснить, что это такое, не погрешив против истины, невозможно. Регистр это нечто такое, что выглядит как регистр, но таковым в действительно не является. В древних машинах регистр был частью устройства обработки данных. Процессор не может сложить два числа, находящихся в оперативной памяти. Сначала он должен взять их в руки (регистры). Это — на микро уровне. Поверх микро уровня расположен интерпретатор машинных кодов, без которого не обходится не один современных процессор (да! да! машинные коды интерпретируются!). PDP-11 уже не требовал от программиста предварительной загрузки данных в регистры, делая вид, что он берет их прямо из памяти. На самом же деле, данные скрыто загружались во внутренние регистры, а после выполнения арифметических операций результат записывался в память или в… "логический" регистр, представляющий собой ячейку очень быстрой памяти.

В x86 регистры так же виртуальны, но в отличие от PDP, частично сохранили свою специализацию. Некоторые команды (например, MUL) работают со строго определенным набором регистров, который не может быть изменен. Это — плата за совместимость со старыми версиями. Другое неприятное ограничение состоит в том, что x86 не поддерживает адресации типа память – память и одно из обрабатываемых чисел обязательно должно находится в регистре или представлять собой непосредственное значение. Фактически, ассемблерная программа наполовину состоит из команд пересылки данных.


Все эти действия происходят на арене, называемой адресным пространством. Адресное пространство — это просто совокупность ячеек виртуальной памяти, доступной процессору. Операционные системы типа Windows 9x и большинство UNIX'ов создают для каждого приложения свой независимый 4 Гбайтный регион, в котором можно выделить по меньшей мере три области: область кода, область данных и стек.

Стек — это такой способ хранения данных. Что-то среднее между списком и массивом (читайте Кнута, от рулез). Команда PUSH кладет новую порцию данных на верхушку стека, а команда POP — снимает. Это позволяет сохранять данные в памяти не заботясь об их абсолютных адресах. Очень удобно! Вызов функций происходит именно так. Команда CALL func забрасывает в стек адрес следующей за ней команды, а RET стягивает его со стека. Указатель на текущую вершину хранится в регистре ESP, а дно… формально стек ограничен лишь протяженностью адресного пространства, а так — количеством выделенной ему памяти. Направление роста стека: от больших адресов — к меньшим. Еще говорят, что стек растет снизу вверх.

Регистр EIP содержит указатель на следующую выполняемую команду и непосредственно недоступен для модификации. Регистры EAX, EBX, ECX, EDX, ESI, EDI, EBP называются регистрами общего назначения и могут свободно участвовать в любых математических операциях или операциях обращения к памяти. Их всего семь. Семь 32-разрядных регистров. Четыре первых из них (EAX, EBX, ECX и EDX) допускают обращения к своим 16-разрядным половинкам, хранящим младшее слово — AX, BX, CX и DX. Каждый из них в свою очередь делиться на старший и младший байты — AH/AL, BH/BL, CH/CL и DH/DL. Важно понять, что AL, AX и EAX это не три разных регистра, а разные части одного и того же регистра!

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


Содержание раздела