Эта статья предназначена для тех, кто если и не собирается стать программистом, но хочет получить хотя бы самые первые понятия об ассемблере. Поработав с простенькой программой, которая уже есть в любом компьютере (называется debug, ехе), можно «почувствовать» работу самого процессора. Об ассемблере стоит получить хотя бы небольшое представление, так как при работе с языками высокого уровня время от времени возникают проблемы.
Многие наслышаны про Ассемблер, боятся его и УВАЖАЮТ, хотели бы понять, а что же он собой представляет. Пользователь может решать, а вдруг ассемблер ему и впрямь понадобится?
Кок заглянуть в регистры «сердца». Шестнадцатеричный «язык»
Ваш компьютер говорит на двоичном и только на двоичном языке. Этот язык называется «машинным». Компьютер только делает вид, что не обижается, когда вы говорите с ним через посредников вроде С++, паскаля, бейсика... Но иногда посреди прикладных программ крепко «прикладывается» и «зависает». Ведь мы даже домашней собачке, играя, говорим «гав-гав». Давайте прямо сейчас и приступим к беседе с вашим домашним любимцем-компьютером. Для этого нам понадобится программа debug.exe. Она прячется в вашем компьютере в папке по адресу с:\ windows\system32.
Запускаем программу. На экране мы видим, как программа знакомится с нами. Как и полагается, учащенный пульс курсора. «Меня зовут Debug» (де Баг - почти как генерал де Голль. Не будем переводить.... Хотя к чему скрывать правду? Переводят как Отладчик, а на самом деле - Ловец Жуков) . В дальнейшем будем называть эту программу Дебаггер. Так принято...
Введем самую первую команду (компьютер, как и собачки, очень любит выполнять их): нужно ввести всего-навсего одну букву г (если вслух, то звучит «ар-р-р!!!», от слова register - место для записи), затем нажать клавишу Enter. Дебагге-ру безразлично, какими буквами вы будете «говорить» с компьютером: строчными или прописными. Дорого внимание. Можно г, можно R. Рычать в ответ не будут.
Прежде чем понять, что же «ответил» нам компьютер, нужно принять небольшую дозу знаний. Помните только, что компьютер пытается открыть вам свое сердце (процессор).
Любая информация может быть введена в компьютер с помощью всего двух цифр - 0 и 1, эти две цифры принято называть битами (Binary digiT). Например, чтобы тайно (т.к. щелкают только клавиши клавиатуры) сообщить компьютеру число 62, нужно ввести 8 битов, т.е. 00111110 - это двоичная запись числа 62. Если число большое, этих единиц и нулей может быть много, и ввести их без ошибок практически невозможно. Но компьютер не жесток к людям, нам дозволено вводить информацию с помощью шестнадцати цифр: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, а, Ь, с, d, е, f. Число 00111110 в этом случае выглядит так - Зе.
Дальнейший автоматический перевод в двоичную систему компьютер берет на себя, щедро отводя при этом на каждую шестнадцатеричную цифру целых ЧЕТЫРЕ бита. Можно не ломать голову над математическими премудростями, а включить «переводчик» с десятичного на шестнадцатеричный язык, запустив программу Калькулятор: Пуск > Программы > Стандартные > Калькулятор > Вид > Инженерный.
Ставим сначала кнопку в положение Dec (decimal - десятичный), набираем число в десятичном виде (например, 62), затем кнопку ставим в положение Hex (от слова hexadecimal) - получается число в шестнадцатеричной записи (в нашем случае Зе).
Можно перевести и на двоичный язык (кнопка в положении Bin, от слова binary). Ясно, что переводить числа можно и в противоположном направлении.
Итак, нам разрешено общаться с компьютером не на его родном «машинном», т.е. двоичном, языке, а на компьютерном шест-надцатеричном, хотя на самом начальном этапе доассемблерной эры программисты честно пытались вводить все эти нули и единицы. Но потом перешли на очень компактный шестнадцатеричный язык (внимание, это еще не ассемблер!), при этом в компьютер вводилась соответствующая про-грамма-«переводчик». Кроме чисел в компьютер можно вводить буквы. Каждая буква кодируется с помощью двух шестнадцатеричных цифр и поэтому занимает 8 битов. Для краткости такую группу из 8 битов называют байтом. Аналогично кодируются знаки препинания и т.п.
Байты, которые мы вводим, от клавиатуры по серому тонкому шнурку (или по хвосту мышки, когда ею «щелкают») вначале поступают непосредственно в процессор в один из регистров, точнее в память процессора, а вот память эта как раз и состоит из регистров. Об их устройстве скажем попозже.
Посмотрим, что получилось. Тут показана вся память процессора, все ее регистры. Достаточно рассмотреть несколько. Сначала идут имена таких регистров, как ах, Ьх, сх, dx (читаются эй-экс, би-экс, си-экс, ди-экс). После их имен далее видим четыре ЦИФРЫ (в данном случае шестнадцатеричные нули). Так как на каждую шестнадцатеричную цифру отводится по четыре бита, то делаем вывод, что указанные регистры состоят из 16 битов. Таким образом, каждый из регистров можно представить в виде коробки с четырьмя «отсеками». В каждом отсеке можно хранить ровно одну шестнадцатеричную цифру.
Еще вывод: пока что в первых четырех регистрах содержатся нули. Но это пока...
Остальные регистры оставим на потом. Можно заметить только, что не во всех регистрах нули. Напри-
мер, в регистре ds (ди-эс) содержится шестнадцатеричное число 0В47, т.е. ноль-би-4-7, можно было написать 0Ь47, то есть десятичное число 2887 (проверить можно с помощью калькулятора).
Введем теперь команду q (кью -от слова quit - завершить). Затем запустим Дебаггер по новой. Придется делать так каждый раз, начиная очередную тему, так как команды очистки нет, к сожалению.
Если нам не хочется видеть содержимое всех регистров, то можно увидеть содержимое только одного какого-нибудь нужного регистра. Посмотрим, например, что находится в регистре ах. Вводим команду г и через пробел имя регистра ах, затем Enter.
Так и есть, в этом регистре одни нули. Если не хотим менять содержимое регистра, нажимаем Enter. Но нам придется научиться менять содержимое регистра, для этого вводим после двоеточия нужные четыре шестнадцатеричные цифры (какие именно, зависит от решаемой задачи) и затем Enter.
В таблице 1 показано устройство регистра ах (в таблице он выделен серым цветом). Он состоит из двух частей. Их имена al (читается эй-эль) и ah (эй-эйч) обозначают правую (low - низшую) и левую (high - высшую) части регистра ах. Каждой части выделен один байт, которые состоят из двух частей по 4 бита каждая. Всего таких 4-битовых отсека четыре. В первой строке показано, что они нумеруются справа налево, то есть, как и положено, от нижних разрядов к высшим.
Аналогично обстоят дела с регистрами bx, сх, dx.
Память
Ясно, что одних регистров процессора для создания компьютер-
ных программ очень мало, поэтому имеется еще несколько видов памяти. Рассмотрим так называемую оперативную память.
Каждая ячейка памяти, в отличие от регистров, представляет собой вместилище для одного байта, т.е. для 8 битов. Пусть, для простоты, память некоторого воображаемого компьютера состоит из 50 ячеек. В компьютере они нумеруются от 0 до 49. Номер ячейки называется ее адресом. Допустим, например, что нужное нам число содержится в ячейке № 27. Мы и командуем компьютеру взять это число из ячейки № 27. Однако в силу технических причин адрес ячейки указывается не явно, а косвенно. Чтобы понять это, память можно представить в виде двумерного массива (это вроде школьной тетрадки в клеточку). При этом строки назовем сегментами, а номера столбцов - смещениями. (Но следует помнить, что это лишь для удобства. На самом деле память одномерна, ячейки как бы «выстроены в одну шеренгу»!)
Однако строки (в новой терминологии - сегменты) нумеруются не как обычно у массивов, а с добавлением лишнего нуля справа. Это дает возможность находить адрес отдельной ячейки не как пару чисел, а как одно число - сумму номеров строки и столбца. Задание адреса ячейки памяти в виде одного числа намного упрощает программирование (табл. 2).
Все ячейки памяти оказались пронумерованными как надо, а именно от 0 до 49. Например, ячейку с прямым адресом 27 в косвенной адресации мы находим в сегменте 20 и в смещении 7. Косвенный адрес в этом случае записывается в виде 2:7. В номере сегмента опускаем ноль,
так как он встречается во всех номерах сегментов и будет в дальнейшем лишь подразумеваться. Таким образом, 2:7 = 20 + 7 = 27. Понятно, что здесь двоеточие - не знак деления.
Адрес ячейки, над которой в данный момент «думает» компьютер, определяется с помощью вполне определенных регистров процессора. Номертекущего сегмента (без правого крайнего нуля) записывается в регистре cs (си-эс, т.е. code segment, сегмент, в котором находится код текущей команды), величина смещения хранится в ячейке ip (ай-пи, т.е. instruction pointer - указатель команды).
Таблица как модель памяти была приведена в десятичной системе счисления.
В шестнадцатеричной системе память моделируется точно так же.
А теперь приведем один и тот же кусочек «настоящей» памяти компьютера в двух форматах.
Десятичный формат: таблица 3.
Шестнадцатеричный формат: таблица 4.
Номера сегментов тоже оканчиваются на 0 (которая на самом деле в косвенной адресации опускается для экономии) и состоят из пяти цифр. Не забываем, что эти шестнадцатеричные цифры записываются с помощью 4 битов каждая. Это значит, что из сегмента cs сначала читается 16-битовое число Odea (мы знаем, что в нашем случае регистр больше 16 битов не берет), к которому затем приписываются справа четыре двоичных нуля.
Подведем итоги. Адрес сегмента занимает 20 битов, в шестнадцатеричной записи оканчивается на один шестнадцатеричный ноль (который при записи косвенного адреса опускается), а в десятичной записи он делятся на 16.
Смещения состоят из четырех цифр (соответствующий регистр для его хранения 16-битовый).
В нашем примере ячейка с абсолютным адресом 0dd39 имеет косвенный адрес 0dca:99.
Продолжение следует...
здорово, как лучше продолжить изучение? хотел бы приступить к програмированию… что посоветуете прочитать в таком же легком тексте