CFA LogoCFA Logo Computer
Загрузка поиска
Новости Компьютеры Прайс-лист [Новое] Прайс-лист [Б/У] Для ноутбуков Конфигуратор ПК Заказ, Оплата, Доставка Сервис объявления Драйвера Статьи Как нас найти Контакты
Новости
RSS канал новостей
То, что энтузиасты ждали так долго, наконец-то случилось, и компания NVIDIA анонсировала свой новый ...
Официальный анонс графического ускорителя GeForce GTX 1080 Ti состоялся 1 марта, и партнеры NVIDIA ...
Компания ASRock представила мировой общественности материнскую плату H110-STX MXM, которая рассчитана ...
Компания MSI в рамках серии Arsenal Gaming представляет пользователям материнские платы линейки ...
По данным наших коллег, в этом месяце компания Huawei официально представит свой новый смартфон. ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2003 ГОД

Язык, на котором говорит компьютер

Михаил ЧЕРКЕС misha_irpen@rambler.ru

Много лет программисты спорят о том, какой язык программирования лучше, мощнее, удобней. И не видно этому спору конца и края, хотя уже давно есть стандарты «де-факто» для той или иной вычислительной задачи. Да и переубедить не менее квалифицированного сторонника того или иного языка — задача совершенно бесперспективная.Но сегодня я не буду продолжать этот извечный и никому не нужный спор. В этой статье я немного расскажу про тот язык, который всегда стоял особняком, — спорщики как правило не затрагивают его в своих «разборках». Это исторически самая первая из тех сущностей, которые принято называть языками программирования. Итак, язык ассемблера.

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

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

Читатель может спросить: чем же принципиально отличается язык ассемблера от того, что можно увидеть, просто открыв EXE-файл в текстовом или шестнадцатеричном редакторе? Какой смысл придумывать язык, команды которого все равно напрямую отождествляются с соответствующими процессорными инструкциями?

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

Ответ на второй вопрос не столь банален, но так же легко объясним. Дело в том, что каждая из инструкций, составляющих готовую программу, при загрузке записывается в оперативную память по определенному адресу, в то же время многие из них содержат в себе значения адреса, по которому находятся нужные данные или другие команды. Таким образом, если в программу длинной сто инструкций добавить хоть один байт, то все команды и данные, которые идут за измененным участком, сместятся и поменяют свой адрес в памяти. Все это приведет к полному разрушению логики работы программы. Чтобы избежать этой неприятности, программист должен после внесения каждого изменения внутри программы просматривать код и изменять ссылки на адреса с учетом смещения. А если программа состоит из десятков тысяч команд? Трудная работенка, согласитесь :-). Транслятор языка ассемблера же делает все эти расчеты самостоятельно один раз при переводе исходного текста в двоичный код, и программист может сосредоточиться на программировании, а не тратить большую часть времени на просмотр программы и модификацию данных в ней.

Еще одно преимущество использования ассемблера перед написанием команд непосредственно в кодах процессора состоит в возможности использования именованных переменных и меток вместо трудно запоминаемых числовых адресов.

Надеюсь, я смог убедить недоумевающих в том, что создание ассемблера еще во времена первых ЭВМ было не роскошью, а насущной необходимостью. Однако несмотря на все удобства, предоставляемые этим языком, он остается весьма сложным для понимания и капризным при реальном использовании. Почему? Да потому что программист все равно должен досконально знать командную систему выбранного процессора, операционной системы, методы управления периферийными устройствами и свойства данных, с которыми приходится иметь дело. Ведь язык оперирует одиночными командами процессора и, в отличие от языков высокого уровня, не имеет никаких встроенных средств ввода-вывода. То есть для того чтобы только ввести с клавиатуры несколько символов и без всякой обработки просто вывести их на экран, уже может потребоваться выполнение десятков процессорных инструкций!

Однако не следует думать, что ассемблер — нечто непостижимо мудреное. Это не так! Ассемблер — самый простой из всех языков, но его простота несколько отличается от простоты BASIC, C или Pascal. Этот язык дает свободу, недостижимую для всех прочих языков, вместе взятых. Но давно известно, что обратной стороной свободы является ответственность, и это как раз про нас: никто, кроме самого программиста, не отвечает за то, какие инструкции и в какой последовательности он использует, в какие области памяти записывает данные и какие команды отдает периферийным устройствам. И хотя создатели современных многозадачных операционных систем и прикладывают максимум усилий к тому, чтобы программа не делала ничего такого, что может быль опасно, все равно программирование на ассемблере — шаг достаточно ответственный.

Самое первое и самое главное, что нужно знать тем, кто хочет писать программы на ассемблере, — это базовое устройство центрального процессора. Это, конечно, не означает, что нужно досконально знать место и функцию каждого из миллионов транзисторов. Я буду рассказывать про язык ассемблера на примере процессоров семейства x86, каковыми и являются все процессоры, используемые сегодня в IBM-совместимых компьютерах.

С точки зрения программиста, процессор представляет собой набор регистров и команд для работы с ними и/или данными в памяти. Регистры представляют собой просто ячейки внутренней памяти процессора (не путать с кэш-памятью). Именно над данными, записанными в этих ячейках, можно выполнять арифметические, логические и все прочие действия, в них же будут записаны результаты этих операций. Система регистров довольно сложна, и ее описание выходит за рамки этой вводной статьи, однако все желающие легко найдут и освоят соответствующий материал.

Что же представляет собой программа на языке ассемблера? Пример последовательности инструкций, которая не делает ничего, кроме вывода в окно DOS простой текстовой строчки, приведен ниже. В этом фрагменте опущены все преамбулы, которые к тому же могут существенно отличаться в разных версиях и реализациях программы-транслятора; вместо этого я сделаю упор на смысловую часть кода.

Числовые метки в левой части текста не являются частью программы и добавлены в текст для того, чтобы удобно было ссылаться на ту или иную строку кода. Итак, что же представляет собой эта простейшая программа? Разберем ее по строчке.

Первая строка содержит команду пересылки шестнадцатеричного числа в регистр AH центрального процессора. Согласно принятому давным-давно правилу, в этот регистр записывается код операции, которую нужно будет выполнить впоследствии. В данном случае это код команды вывода на экран подготовленной заранее текстовой строки.

Вторая строка записывает в регистр DX адрес, по которому в памяти будет находится текстовая строка. Директива Offset при трансляции программы в машинный код заменяется на конкретный числовой адрес.

Третья строка представляет собой команду вызова функции операционной системы. Эта функция проанализирует содержимое регистров процессора и выполнит нужное нам действие. В данном случае произойдет чтение из памяти текстовой строки и вывод ее на экран в соответствии с текущими настройками экрана. При программировании на ассемблере вам часто придется использовать сервис, предоставляемый операционной системой, чтобы не беспокоиться о типе, настройках и текущем состоянии оборудования ввода-вывода. Но это не означает что при наличии желания нельзя реализовать все это самостоятельно. К тому же иногда этого просто требует необходимость ускорить работу программы.

Четвертая строка содержит команду возврата из текущего блока программы, а так как весь текст и так представляет собой единый блок, то эта команда приведет к завершению работы и передаст управление операционной системе. В необходимости этой команды кроется еще одно важное отличие ассемблера от языков высокого уровня —программа никогда не может просто закончиться, вместо этого она всегда должна передавать управление той программе, которая произвела ее запуск (чаще всего это сама операционная система). Если этого не сделать, то процессор будет продолжать выполнять те команды, которые находятся в памяти после нашей программы, а там может быть все что угодно: фрагменты других программ, которые выполнялись или выполняются, простой «мусор» или, как в нашем случае, совершенно не предназначенные для непосредственного выполнения процессором текстовые данные.

Пятая и последняя строка содержит ту самую последовательность символов, которую выводит на экран программа. Функция 09h требует, чтобы строка заканчивалась символом $, иначе после полезного текста на экран начнут выводится символы, которые находятся в памяти после программы, и так будет продолжаться до тех пор, пока среди них не встретится искомый «доллар». Сам заключительный символ на экран, конечно же, не попадает. Нужно также иметь в виду, что не все трансляторы позволяют ссылаться на данные до того, как они объявлены в тексте, однако такая форма является самой простой и исторически наиболее ранней. А при использовании не абстрактного ассемблера, а конкретного транслятора в исходном коде обычно отводится специальный раздел для объявления переменных и констант, но это опять же может сильно зависеть от версии транслятора.

Из приведенного примера видно, что ассемблер не может являться полноценным структурным языком программирования по той причине, что одна строка исходного кода практически никогда не означает законченное действие. Это можно сравнить с человеческой речью — звуки складываются в слова, слова знаками препинания оформляются в высказывания; при этом надо помнить все ранее произнесенные звуки со знаками препинания на протяжении всей фразы, пока не будет произнесен самый последний звук и высказывание не обретет законченный смысл. Именно из-за этой неинформативности языковой единицы ассемблер считается сложным и труднопонимаемым языком. К сожалению, отчасти это так и есть.

И хотя сегодня на фоне гигагерцовых процессоров и сотен мегабайт оперативной памяти актуальность ассемблера как средства эффективного программирования заметно упала, все равно наиболее критичные участки «тяжелых» программ, в частности игр, пишутся с использованием именно этого языка. Кроме того, современные трансляторы предоставляют даже средства разработки с использованием идеологии объектно-ориентированного программирования.

Я надеюсь, что мне не удалось отбить у вас охоту осваивать это великолепное и удивительно мощное орудие программирования :-). Удачи вам!

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы: *
captcha
Обновить






Рейтинг@Mail.ru
Хостинг на серверах в Украине, США и Германии. © www.sector.biz.ua 2006-2015 design by Vadim Popov