Assebler — assembler-актуальность его использования


Содержание

Введение

Для начала разберёмся с терминологией.

Машинный код – система команд конкретной вычислительной машины (процессора), которая интерпретируется непосредственно процессором. Команда, как правило, представляет собой целое число, которое записывается в регистр процессора. Процессор читает это число и выполняет операцию, которая соответствует этой команде. Популярно это описано в книге Как стать программистом.

Язык программирования низкого уровня (низкоуровневый язык программирования) – это язык программирования, максимально приближённый к программированию в машинных кодах. В отличие от машинных кодов, в языке низкого уровня каждой команде соответствует не число, а сокращённое название команды (мнемоника). Например, команда ADD – это сокращение от слова ADDITION (сложение). Поэтому использование языка низкого уровня существенно упрощает написание и чтение программ (по сравнению с программированием в машинных кодах). Язык низкого уровня привязан к конкретному процессору. Например, если вы написали программу на языке низкого уровня для процессора PIC, то можете быть уверены, что она не будет работать с процессором AVR.

Язык программирования высокого уровня – это язык программирования, максимально приближённый к человеческому языку (обычно к английскому, но есть языки программирования на национальных языках, например, язык 1С основан на русском языке). Язык высокого уровня практически не привязан ни к конкретному процессору, ни к операционной системе (если не используются специфические директивы).

Язык ассемблера – это низкоуровневый язык программирования, на котором вы пишите свои программы. Для каждого процессора существует свой язык ассемблера.

Ассемблер – это специальная программа, которая преобразует (компилирует) исходные тексты вашей программы, написанной на языке ассемблера, в исполняемый файл (файл с расширением EXE или COM). Если быть точным, то для создания исполняемого файла требуются дополнительные программы, а не только ассемблер. Но об этом позже…

В большинстве случаев говорят «ассемблер», а подразумевают «язык ассемблера». Теперь вы знаете, что это разные вещи и так говорить не совсем правильно. Хотя все программисты вас поймут.

В этой книге мы будем говорить только о программировании для компьютеров с процессорами Intel (или совместимыми). Для того чтобы на практике проверить приведённые в книге примеры, вам потребуются следующие программы (или хотя бы некоторые из них):

  1. Emu8086. Хорошая программа, особенно для новичков. Включает в себя редактор исходного кода и некоторые другие полезные вещи. Работает в Windows, хотя программы пишутся под DOS. К сожалению, программа стоит денег (но оно того стоит))). Подробности см. на сайте http://www.emu8086.com.
  2. TASM – Турбо Ассемблер от фирмы Borland. Можно создавать программы как для DOS так и для Windows. Тоже стоит денег и в данный момент уже не поддерживается (да и фирмы Borland уже не существует). А вообще вещь хорошая.
  3. MASM – Ассемблер от компании Microsoft (расшифровывается как МАКРО ассемблер, а не Microsoft Assembler, как думают многие непосвящённые). Пожалуй, самый популярный ассемблер для процессоров Intel. Поддерживается до сих пор. Условно бесплатная программа. То есть, если вы будете покупать её отдельно, то она будет стоить денег. Но она доступна бесплатно подписчикам MSDN и входит в пакет программ Visual Studio от Microsoft.
  4. WASM – ассемблер от компании Watcom. Как и все другие, обладает преимуществами и недостатками.
  5. Debug — обладает скромными возможностями, но имеет большой плюс — входит в стандартный набор Windows. Поищите ее в папке WINDOWS\COMMAND или WINDOWS\SYSTEM32. Если не найдете, тогда в других папках каталога WINDOWS.
  6. Желательно также иметь какой-нибудь шестнадцатеричный редактор. Не помешает и досовский файловый менеджер, например Волков Коммандер (VC) или Нортон Коммандер (NC). С их помощью можно также посмотреть шестнадцатеричные коды файла, но редактировать нельзя. Бесплатных шестнадцатеричных редакторов в Интернете довольно много. Вот один из них: McAfee FileInsight v2.1. Этот же редактор можно использовать для работы с исходными текстами программ. Однако мне больше нравится делать это с помощью следующего редактора:
  7. Текстовый редактор. Необходим для написания исходных текстов ваших программ. Могу порекомендовать бесплатный редактор PSPad, который поддерживает множество языков программирования, в том числе и язык Ассемблера.

Все представленные в этой книге программы (и примеры программ) проверены на работоспособность. И именно эти программы используются для реализации примеров программ, приведённых в данной книге.

И еще – исходный код, написанный, например для Emu8086, будет немного отличаться от кода, написанного, например, для TASM. Эти отличия будут оговорены.

Большая часть программ, приведённых в книге, написана для MASM. Во-первых, потому что этот ассемблер наиболее популярен и до сих пор поддерживается. Во-вторых, потому что он поставляется с MSDN и с пакетом программ Visual Studio от Microsoft. Ну и в третьих, потому что я являюсь счастливым обладателем лицензионной копии MASM.

Если же у вас уже есть какой-либо ассемблер, не вошедший в перечисленный выше список, то вам придётся самостоятельно разобраться с его синтаксисом и почитать руководство пользователя, чтобы научиться правильно с ним работать. Но общие рекомендации, приведённые в данной книге, будут справедливы для любых (ну или почти для любых) ассемблеров.

Assebler — assembler-актуальность его использования

В данной главе мы поговорим о двух конкурирующих продуктах MASM и TASM, их плюсах и минусах, общих чертах и различиях. Когда в конце 80-х я впервые «пересел» на «айбиэмки», первый вопрос, который я задал знающим людям, был об ассемблере. До этого я программировал на разных компьютерах, в основном имеющих весьма ограниченные ресурсы. Естественно, что основным языком на таких компьютерах был ассемблер 27 . Мне дали MASM, кажется, это была вторая версия. Удивительно, но тогда на ассемблере я начал писать что-то типа баз данных. Проект мой не был закончен, но к ассемблеру я прикипел основательно. Потом мне попался Турбо Ассемблер версии 1.0. Он работал гораздо быстрее MASM. В дальнейшем мне приходилось использовать то один, то другой ассемблер. Как Вы, наверное, уже поняли, первая любовь оказалась сильнее, но теперь нам придется серьезно поговорить о том, что же все-таки предпочтительнее использовать при программировании в операционной системе Windows.

27 Одно время в образовании был широко распространен персональный компьютер «Ямаха», ОЗУ которого составляла всего 64 Кб (потом 128). Писать для такого компьютера, скажем, на языке Паскаль было, естественно, непозволительной роскошью.

Начнем со справочной информации о параметрах командной строки ML.EXE и TASM32.EXE. В начале рассмотрим транслятор ML.EXE.

Параметр Комментарий
/? Вывод помощи.
/AT Создать файл в формате .СОМ. Для программирования в Windows этот ключ, естественно, бесполезен.
/Bl Использовать альтернативный компоновщик. Предполагается автоматический запуск компоновщика.
/c Компиляция без компоновки.
/Ср Сохранение регистров пользовательских идентификаторов. Может использоваться для дополнительного контроля.
/Cu Приведение всех пользовательских идентификаторов к верхнему регистру.
/Сх Сохранение регистров пользовательских идентификаторов, объявленных PUBLIC и EXTERNAL.
/coff Создание объектных файлов в стандарте coff. Применение обязательно.
Задание текстового макроса. Очень удобен для отладки с использованием условной компиляции.
/ЕР Листинг: текст программы с включаемыми файлами.
/F Размер стека в байтах. Размер стека по умолчанию равен 1 Мб.
/Fe Имя исполняемого файла. Имеет смысл без параметра /с.
/Fl Создать файл листинга.
/Fm Создать map-файл. Имеет смысл без опции /с.
/Fo Задать имя объектного файла.
/Fpi Включение кода эмулятора сопроцессора. Начиная с 486-ого микропроцессора, данный параметр потерял актуальность.
/Fr Включить ограниченную информацию браузера.
/FR Включить полную информацию браузера.
/G Использовать соглашение вызова Паскаль, Си, stdcall.
/H Установить максимальную длину внешних имен.
/I Добавить путь для inc-файлов. Допускается до 10 опций /I.
/link Опции командной строки компоновщика. Имеет смысл без опции /с.
/nologo Не показывать заголовочный текст компилятора.
/Sa Листинг максимального формата.
/Sc Включить в листинг синхронизацию.
/Sf Листинг первого прохода.
/Sl Длина строки листинга.
/Sn Не включать в листинг таблицу символов.
/Sp Высота страницы листинга.
/Ss Текст подзаголовка листинга.
/St Текст заголовка листинга.
/Sx Включить в листинг фрагменты условной компиляции.
/Ta Для компилирования файлов, расширение которых не .asm.
/W Устанавливает перечень событий компиляции, трактуемые как предупреждения.
/WX Трактовать предупреждения как ошибки.
/w Тоже что /W0 /WX.
/X Игнорировать путь, установленный переменной окружения INCLUDE.
/Zd Отладочная информация состоит только из номеров строк.
/Zf Объявить все имена PUBLIC.
/Zi Включить полную отладочную информацию.
/Zm Включить совместимость с MASM 5.01.
/Zp Установить выравнивание структур.
/Zs Выполнять только проверку синтаксиса.
Параметр Комментарий
/? или /h Вывод помощи.
/a Сегменты в объектном файле располагаются в алфавитном порядке.
/s Сегменты в объектном файле расположены в порядке их описания.
Задание текстового макроса. Очень удобен для отладки с использованием условной компиляции.
/e Включение кода эмуляции сопроцессора.
/r Разрешение инструкций сопроцессора.
/i Добавить путь для inc-файлов. Синтаксис такой же, как у команды РАТН.
/j Определяет директиву, которая будет транслироваться перед трансляцией.
/kh Задается максимальное количество идентификаторов. По умолчанию 16384.
/l Создавать файл листинга.
/la Показать в листинге код, вставляемый транслятором для организации интерфейса с языками высокого уровня.
/ml Различать прописные и строчные буквы в идентификаторах.
/mx Различать прописные и строчные буквы в идентификаторах PUBLIC и EXTERNAL.
/mu Считать все символы в идентификаторах как прописные.
/mv Установить максимальную длину идентификатора.
/m Установка количества проходов транслятора. По умолчанию это число равно 1.
/n Не выдавать в файле листинга таблицы идентификаторов.
/os, /o, /op, /oi Тип объектного кода: стандартный, оверлейный, Phar Lap, IBM.
/p Проверять наличие кода с побочными эффектами при работе в защищенном режиме.
/q Удаление из объектного кода лишней информации.
/t Подавление вывода всех сообщений при условном ассемблировании.
/w0, /w1, /w2 Уровень полноты сообщений: сообщения не генерируются, сообщения генерируются.
/w- /w+ Генереция (+) или ее отсутствие (-) сообщений класса xxx.
/x Включить в листинг блоки условного ассемблирования.
/z Выводить не только сообщения об ошибках, но строку с ошибкой.
/zi Включить в объектный код информацию для отладки.
/zd Поместить в объектный код номера строк.
/zn Не помещать в объектный код отладочной информации.

В этой таблице объяснение опции помещено под строкой, содержащей эту опцию.

/ALIGN:number
Определяет выравнивание секций в линейной модели. По умолчанию 4096.

/BASE:Определяет базовый адрес (адрес загрузки). По умолчанию для ЕХЕ-программы адрес 0х400000, для DLL — 0х10000000.

/COMMENT:[«]comment[«]
Определяет комментарий, помещаемый в заголовок ЕХЕ- и DLL-файлов.

/DEBUG
Создает отладочную информацию для ЕХЕ- и DLL-файлов. Отладочная информация помещается в pdb-файл.

/DEBUGTYPE:
CV — отладочная информация в формате Microsoft, COFF — отладочная информация в формате COFF (Common Object File Format), BOTH — создаются оба вида отладочной информации.

/DEF:filename
Определяет DEF-файл.

/DEFAULTLIB:library
Добавляет одну библиотеку к списку используемых библиотек.

/DLL Создать DLL-файл.

/DRIVER[:]
Используется для создания NT-драйвера (Kernel Mode Driver).

/ENTRY:symbol
Определяет стартовый адрес для ЕХЕ- и DLL-файлов.

/EXETYPE:DYNAMIC
Данная опция используется при создании VxD-драйвера.

/EXPORT:entryname[=internalname][,@ordinal[,NONAME]][,DATA]
Данная опция позволяет экспортировать функцию из вашей программы так, чтобы она была доступна для других программ. При этом создается import-библиотека.

/FIXED[:NO]
Данная опция фиксирует базовый адрес, определенный в опции /BASE.

/FORCE[:]
Позволяет создавать исполняемый файл, даже если не найдено внешнее имя или имеется несколько разных определений.

/GPSIZE:number
Определяет размер общих переменных для MIPS и Alpha платформ.

/HEAP:reserve[,commit]
Определяет размер кучи (HEAP) в байтах. По умолчанию этот размер равен одному мегабайту.

/IMPLIB:filename
Определяет имя import-библиотеки, если она создается.

/INCLUDE:symbol
Добавляет имя к таблице имен.

/INCREMENTAL:
Если установлена опция /INCREMENTAL:YES, то в ЕХЕ добавляется дополнительная информация, позволяющая быстрее перекомпилировать этот файл. По умолчанию это информация не добавляется.

/LARGEADDRESSAWARE[:NO]
Указывает, что приложение оперирует адресами, большими 2 Гб.

/LIBPATH:dir
Определяет библиотеку, которая в первую очередь разыскивается компоновщиком.

/MACHINE:
Определяет платформу. В большинстве случаев это делать не приходится.

/MAP[:filename]
Дает команду создания МАР-файла.

/MAPINFO:
Указывает компоновщику включить соответствующую информацию в МАР-файл.

/MERGE:from=to
Объединить секцию «from» с секцией «to» и присвоить имя «to».

/NODEFAULTLIB[:library]
Игнорирует все или конкретную библиотеку.

/NOENTRY
Необходимо для создания DLL-файла.

/NOLOGO
Не выводить начальное сообщение компоновщика.

/OPT:
Определяет способ оптимизации, которую выполняет компоновщик.

/ORDER:@filename
Оптимизация программы путем вставки определенных инициализированных данных (COMDAT).

/OUT:filename
Определяет выходной файл.

/PDB:
Определить имя файла, содержащего информацию для отладки.

/PROFILE
Используется для работы с профайлером (анализатором работы программы).

/RELEASE
Помещает контрольную сумму в выходной файл.

/SECTION:name,[E][R][W][S][D][K][L][P][X]
Данная опция позволяет изменить атрибут секции.

/STACK:reserve[,commit]
Определяет размер выделяемого стека. Commit — определяет размер памяти, интерпретируемый операционной системой.

/STUB:filename
Определяет STUB-файл, запускающийся в системе MS DOS.

/SUBSYSTEM:[,#[.##]]
Определяет, как запускать ЕХЕ-файл. CONSOLE — консольное приложение, WINDOWS — обычные WINDOWS-приложения, NATIVE — приложение для Windows NT, POSIX — создает приложение в POSIX-подсистеме WINDOWS NT.

/SWAPRUN:
Сообщает операционной системе скопировать выходной файл в swap-файл (WINDOWS NT).

/VERBOSE[:LIB]
Заставляет выводить информацию о процессе компоновки.

/VERSION:#[.#]
Помещает информацию о версии в ЕХЕ-заголовок.

/VXD
Создать VXD-драйвер.

/WARN[:warninglevel]
Определяет количество возможных предупреждений, выдаваемых компоновщиком.

/WS:AGGRESSIVE
Несколько уменьшает скорость выполнения приложения (Windows NT). Операционная система удаляет данное приложение из памяти в случае его простоя.

В пакетах Borland С, начиная с 1997 года, сосуществовали две программы для компоновки объектных файлов: tlink32.exe и ilink32.exe. Опции этих программ практически совпадали, ilink32.exe — инкрементальный, или пошаговый, компоновщик. Он хранит информацию о предыдущих компоновках, что позволяет значительно ускорить весь процесс повторных трансляций. В последнее время программа tlink32.exe вообще исчезла из поставки. В дальнейшем мы не будем делать различий между этими двумя программами. Опции, помеченные (+), появились в новых версиях ilink32.exe, а опции со знаком (-), наоборот, исчезли. В новых версиях для выделения опции используется «/» вместо тире.

-m Создать МАР-файл с информацией о сегментах и два листинга с PUBLIC-именами (в алфавитном и адресном порядке).
-s Детальная информация о сегментах в МАР-файле.
-M Поместить в МАР-файл сокращенные имена идентификаторов.
-c Различать прописные и заглавные буквы в PUBLIC и EXTERNAL именах.
-Enn Задает максимальное количество ошибок, приводящее к остановке компоновки.
-P- Запретить паковать сегменты. Имеет смысл для 16-битных приложений (-P — разрешить).
-b:хххх Задает базовый адрес. По умолчанию базовый адрес равен 400000Н. (+)
-B:хххх Аналогично опции -b, но не создает таблицу настройки. Ключи —b и -B могут несколько ускорить работу программы.
-wxxx Возможные предупреждения. Например, -w-stk игнорировать отсутствие стекового сегмента.
-Txx -Tpx PE image(x: е=ЕХЕ, d=DLL) Тип выходного файла. Tpe — создать ЕХЕ-файл. Tpd — создать DLL-файл. Tpp — создать пакетный файл. (+)
-ax -ap -aa -ар — создать консольное приложение, -аа — создать обычное Windows-приложение (GUI), -ad — создать 32-битный драйвер для Windows.(+)
-r Заставляет компоновщик выдавать информацию о процессе компоновки.
-Vd.d Помещает в ЕХЕ-заголовок ожидаемую версию Windows.
-Ud.d Поместить в заголовок ЕХЕ-файла номер версии программы. (+)
-o Импорт по номеру функции. (-)
-Ao:nnnn Определяет величину выравнивания (кратно 2, минимально 16).
-Af:nnnn Файл выравнивания.
-Sc:xxxx Определить размер стека.
-S:xxxx Определить размер резервного стека. Минимально 4К.
-Hc:хххх Определить размер специальной «кучи».
-H:хххх Определить размер резервной «кучи».
-n Нет библиотеки «по умолчанию». (-)
-v Поместить в исполняемый файл полную отладочную информацию. Можно использовать -v+ и -v- для селективного помещения отладочной информации в отдельные файлы.
-j Определить путь поиска OBJ-файлов.
-L Определить путь к LIB-библиотеке.
-x Не создавать МАР-файл.
-Rr Позволяет заменять или добавлять ресурсы. (+)
-d Установить задержку загрузки библиотеки DLL. Она будет загружаться лишь при вызове входной процедуры. (+)
-Dxxxx Поместить в PE-заголовок специальный дескриптор.
-GC Поместить в заголовок РЕ строку (или строки). Например -GC»Hellow!». (+)
-GD Генерировать Delphi-совместимый файл ресурсов. (+)
-GF Установить флаг для загрузочного модуля: SWAPNET — указание для операционной системы поместить загрузочный модуль в swap-файл и загружать его оттуда, если он расположен на сетевом устройстве. SWAPCD — аналогично предыдущему флагу, но для съемных устройств. UNIPROCESSOR — приложение не должно запускаться в мультипроцессорной системе. LARGEADDRESSAWARE — приложение использует адреса больше 4 Gb. AGGRESSIVE — операционная система удаляет приложение из памяти в случае его простоя.(+)
-Gk Заставляет компоновщик оставлять в случае ошибки те файлы, которые обычно в этом случае уничтожались.(+)
-Gl Генерировать LIB-файл.(+)
-Gpr Создавать пакет «времени исполнения».(+)
-Gpd Создать пакет «времени создания».(+)
-Gn Запретить пошаговую компиляцию.(+)
-GS:string=[ECIRWSDKP] Добавляет флаги к уже существующим флагам секций.(+)
-Gz Помещает в РЕ-заголовок контрольную сумму загрузочного модуля.

На первый взгляд трудно выявить предпочтение между MASM32 и TASM32. Но все же:

  1. MASM32 несколько более богат возможностями. Я имею в виду опции командной строки.
  2. TASM32 перестал поддерживаться как отдельный продукт. В связи с этим MASM обошел конкурента по количеству содержащихся в пакете примеров, документации, библиотек и т.д.
  3. TASM32 осуществляет более сложный алгоритм вызова API-функций, а это приводит к тому, что исполняемые модули в TASM32 получаются несколько большими, чем в MASM32.

Завершая главу, приведу несколько простых примеров.

Включение в исполняемый файл отладочной информации. Если в исполняемый файл была включена отладочная информация, то фирменный отладчик позволяет работать одновременно и с текстом программы, и с дизассемблированным кодом. Это особенно удобно для языков высокого уровня, а для программ на ассемблере это весьма мощный инструмент отладки. Пусть текст программы содержится в файле PROG.ASM. Для того чтобы включить отладочную информацию в исполняемый модуль, используем при трансляции следующие ключи:

ML /c /coff /Zd /Zi prog.asm
LINK /subsystem:windows /debug prog.obj

При этом кроме файла PROG.EXE на диске появится файл PROG.PDB, содержащий отладочные данные. Теперь для отладки следует запустить фирменный 32-битный отладчик фирмы Microsoft — Code View.

TASM32 /ml /zi prog.asm
TLINK32 -aa -v prog.obj

В результате в модуль PROG.EXE будет включена отладочная информация. Для отладки такого модуля следует использовать 32-битный Turbo Debugger — TD32.EXE. На Рис. 1.5.1 представлено окно отладчика с отлаживаемой программой. Можно видеть, что на экране имеется и текст программы, и ее дизассемблированный код. Более подробно об отладчиках мы будем говорить в последней части книги.

Получение консольных и GUI приложений. О консольных приложениях речь еще впереди, здесь же я буду краток. Консольные приложения — это приложения, работающие с текстовым экраном, при этом они являются полнокровными 32- битными программами. О структуре консольных программ речь пойдет ниже, сейчас же заметим, что для получения консольного приложения с помощью TLINK32.EXE вместо ключа -aa следует использовать -ар. Что касается компоновщика из пакета MASM32, то здесь следует использовать ключ /subsystem:console вместо /subsystem:windows.

Рис. 1.5.1. Окно TD32.EXE с отлаживаемой программой.

Нужны ответы

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

Найти и выписать параметры не менее трех современных ассемблеров для различных типов процессоров. Под параметрами понимается разрядность, количество команд, формат кодирования.
2. Найти и выписать описание и примеры использования не менее трех команд (исключая простейшие, типа mov, sub и пр.), применяемых в современных ассемблерах для различных типов процессоров.
3. Найти и выписать описание и примеры использования не менее трех директив, применяемых в современных ассемблерах для различных типов процессоров.
4. Найти и выписать параметры не менее трех регистров современных процессоров. Под параметрами понимается разрядность, типичное применение.
5. Найти и выписать не менее трех программ (чаще всего это ядра операционных систем), написанных с использованием чистого языка ассемблера, указать их параметры. Под параметрами понимается размер, разрядность, тип целевого процессора.
6. Подготовить не менее трех предложений по использованию языка ассемблера при разработке современных программ. Предложения должны включать актуальность, цель, задачи и обоснование целесообразности использования ассемблера.
7. Отчеты по лабораторным заданиям (1-5), (письменные ответы на контрольные вопросы), а также электронные версии текстов готовых программ.
8. Отчет по индивидуальному домашнему заданию. Отчет включает составленную от руки блок-схему алгоритма работы программы и электронную версию текста готовой программы.

Тема лекции 3. Язык Ассемблер. Структура программы на ассемблере. Использование сегментов в микропроцессоре I 8086

Ассемблер — это машинно-ориентированный язык представления программ, написанных в машинных кодах. Он дает программисту следующие возможности:

-использовать символические обозначения машинных команд (мнемокоды);

-присваивать символические имена регистрам и ячейкам памяти;

-использовать различные системы счисления и арифметические и логические

выражения для записи чисел и др.

Перевод программы, написанной на языке Ассемблера, на язык компьютера осуществляет транслятор, также называемый ассемблером.

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

делятся на две группы: команды и директивы (псевдокоманды). При

трансляции команды переводятся в машинный код, трансляция директивы сводится к ее выполнению в ходе трансляции.

Команда, записанная на языке Ассемблера, имеет следующий вид: [Метка:] Мнемокод [Операнды] [; Комментарии],

где в квадратные скобки помещены необязательные поля команды. Приведенные поля команд отделяются друг от друга пробелами, либо знаками табуляции — Tab. Поле метки служит для присваивания команде имени, по которому на нее могут ссылаться другие команды, например, команды передачи управления. Метка должна заканчиваться двоеточием, состоять из латинских букв, цифр и специальных символов «?», «@», «_» и «$», при этом первым символом не может быть цифра. Поле мнемокода содержит название команды ЦП. Поле операндов содержит информацию о местонахождении данных, подлежащих обработке. В некоторых случаях, когда операнды заданы по умолчанию (строковые команды, XLAT и др.) или вовсе не нужны (команда NOP), это поле пустое. В командах с двумя операндами первый является приемником результата, второй — источником информации. Поле комментариев содержит текст, поясняющий работу программы. Комментарий может занимать всю строку, если в первой позиции указать точку с запятой. Псевдокоманды записываются в следующем виде:

[Идентификатор] Псевдокоманда [Операнды] [; Комментарии], где в квадратные скобки помещены необязательные поля псевдокоманды. Приведенные поля псевдокоманд отделяются друг от друга пробелами либо знаками табуляции.

Исходный текст программы заканчивается директивой END, завершающей трансляцию, ей указывается точка входа в программу.

Физическая память, к которой микропроцессор имеет доступ по шине адреса, называется оперативной памятью (или оперативным запоминающим устройством — ОЗУ). На самом нижнем уровне память компьютера можно рассматривать как массив битов. Один бит может хранить значение О или 1. ОЗУ организовано как последовательность ячеек — байтов. Один байт состоит из 8 бит. Каждому байту соответствует свой уникальный адрес (его номер), называемый физическим. Диапазон значений физических адресов зависит от разрядности шины адреса

микропроцессора. Для i486 и Pentium он находится в пределах от 0 до 2 — 1 (4

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

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

Под физическим адресом понимается адрес памяти, выдаваемый на шину адреса микропроцессора Другое название этого адреса — линейный адрес. Эта двойственность в названии обусловлена наличием страничной модели организации оперативной памяти. Эти названия являются синонимами только при отключении страничного преобразования адреса (в реальном режиме страничная адресация всегда отключена).

Формирование физического адреса в реальном режиме

В реальном режиме механизм адресации физической памяти имеет следующие характеристики:

— диапазон изменения физического адреса от 0 до 1 Мбайт. Эта величина определяется тем, что шина адреса i8086 имела 20 линий;

— максимальный размер сегмента 64 Кбайт. Это объясняется 16­разрядной архитектурой i8086. Таким образом максимальное значение, которое могут содержать 16-разрядные регистры, составляет 2 16 — 1, что применительно к памяти и определяет величину 64 Кбайт;

Для обращения к конкретному физическому адресу оперативной памяти необходимо определить адрес начала сегмента (сегментную составляющую)и смещение внутри сегмента. Сегменты располагаются в памяти на границе паpагpафов

(паpагpаф — объем памяти pазмеpом в 16 байт), поэтому в адресе начала сегмента последняя цифра равна нулю. Напpимеp:10000h, 1FFF0h. (Таким образом, в сегментном регистре достаточно хранить только старшие 16 бит физического адреса начала сегмента. Недостающие младшие нулевые четыре бита 20-битного адреса получаются сдвигом значения в сегментном регистре влево на 4 разряда. Эта операция сдвига выполняется аппаратно и для программного обеспечения абсолютно прозрачна. Получившееся 20-битное значение и является настоящим физическим адресом, соответствующим началу сегмента. Что касается второго компонента, участвующего в образовании физического адреса некоторого объекта в памяти, — смещения, — то оно представляет собой 16-битное значение. Это значение может содержаться явно в команде либо косвенно в одном из регистров общего назначения. В микропроцессоре эти две составляющие складываются на аппаратном уровне, в результате чего получается физический адрес памяти размерностью 20 бит. Данный механизм образования физического адреса позволяет сделать программное обеспечение перемещаемым, то есть не зависящим от конкретных адресов загрузки его в оперативной памяти.)

(Следует заметить следующее о несоответствии размеров шины адреса микропроцессора i486 или Pentium (32 бита) и 20-битного значения физического адреса реального режима. Пока микропроцессор находится в реальном режиме, старшие 12 линий шины адреса недоступны, хотя при определенных условиях и существует возможность работы с первыми 64 Кбайт оперативной памяти, лежащими сразу после первого мегабайта.)

Так как в реальном режиме адреса сегментов хранятся в сегментных pегистpах, а адреса смещений — в pегистpе IP для сегмента кода, в одном из pегистpов BX,SI,DI для сегмента данных, в одном из pегистpов SP, BP для сегмента стека и в pегистpе DI для дополнительного сегмента данных, то микpопpоцессоp вычисляет адреса памяти доступа к сегменту данных по формулам:

(DS)x16 + BX или (ds)x16 + S1 или (ds)x16 + D1 к сегменту кода:

(CS)x16 + (IP) к сегменту стека:

(SS)x16 + SP или (SS)x16 + BP

к дополнительному сегменту данных:

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


Слова в памяти располагаются в обратном порядке, по правилу младший байт находится по младшему адресу.

Например: Задан массив слов DW 0110h , 0220H , 0330h, 0440h В памяти он будет представлен : DS:0000 10 01 20 02 30 03 40 04 Основная литература :5[46,120-125],8[21-32]7 [40-50].

1. Какие возможности предоставляет ассемблер программисту?

2. Какой вид имеет команда, записанная на языке Ассемблера?

3. Какой вид имеет псевдокоманда на языке Ассемблера?

4. Как определяется эффективный адрес?

5. Как вычисляется физический адрес в реальном режиме?

Тема лекции 4.Описание данных. Режимы адресации.

Для определения данных используются, главным образом, три директивы ассемблера: db (define byte, определить байт) длёя записи байтов, dw (define word, определить слово) для записи слов и dd (define double, определить двойное слово) для записи двойных слов:

size dw 256 ;В ячейку size записывается

;десятичное число 256

setb7 db 80h ;Bячейку setb7записывается

;1б-ричное число 80h

Для резервирования места под массивы используется оператор dup (duplicate, дублировать), который позволяет «размножить» байт, слово или двойное слово заданное число раз:

rawdata dw 300 dup (1) ;Резервируются 300 слов,

;заполненных числом 1

string db 80 dup («) /Резервируются 80 байтов,

Кроме перечисленных, имеются и другие директивы, например df (define farword, определить поле из 6 байт), dq (define quadword, определить четверное слово) или dt (define teraword, определить 10-байтовую переменную), но они используются значительно реже.

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

Способы задания операндов команды определяют режимы адресации.

Все обращения к данным делятся на три типа:

• Обращения к непосредственным данным

• Обращения к данным в регистрах

• Обращения к данным в памяти

Важно то, что один операнд может располагаться в регистре или памяти, а второй операнд обязательно должен находиться в регистре или непосредственно в команде. Непосредственный операнд может быть только операндом- источником.

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

Непосредственная адресация (непосредственный операнд) — операнд задается в самой команд ,т.е его значения записываются прямо в машинном коде команд.

Например: mov ах, 5

-ассемблер генерирует машинный код, соответствующий команде mov, которая загружает в регистр ах непосредственное значение 5. Значение 5 записывается в ассемблированном машинном коде команды mov. В большинстве случаев непосредственные данные являются либо единственным операндом, либо вторым из двух операндов.

Регистровая адресация- операнд находится в одном из регистров Машинный код, создаваемый ассемблером для регистровых данных, содержит соответствующие значения, позволяющие команде оперировать заданными регистрами,

Например: mov ax, bx

В качестве регистров могут использоваться:

— 32-разрядные регистры ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ESP, EBP; — 16­разрядные регистры АХ, ВХ, СХ, DX, SI, DI, SP, ВР; — 8-разрядные регистры АН, AL, BH, BL, CH, CL, DH, DL; —

сегментные регистры CS, DS, SS, ES, FS, GS.

Основные виды адресации операндов в памяти. Цель всех разновидностей данной адресации- помочь процессору вычислить 16-битовое беззнаковое значение, называемое эффективным адресом, или ЭА. ЭА показывает смещение, начиная от базового сегмента, адресуемого одним из четырех сегментных регистров: cs, ds, es, ss. (Сегментный регистр и смещение образуют 32-битовый логический адрес, который в дальнейшем преобразуется в 20-битовый физический адрес, однозначно определяющий положение байта в памяти.) Общее число режимов адресации, т.е способов обращения к операндам определяется архитектурой микропроцессора (так по документации только микропроцессор 8088 имеет 24 режима адресации операндов!).

Основные виды адресации операндов в памяти : прямая, косвенная ,базовая ,индексная , базово-индексная.

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

meml dw 0; слово памяти содержит 0 mem2 db 230; байт памяти содержит 230 ;Сегмент команд

inc meml ; Содержимое слова meml увеличивается на 1 mov DX, meml ; Содержимое слова с именем meml загружается в DX mov AL,mem2 ;Содержимое байта с именем mem2 загружается в AL При прямой адресации можно использовать выражение, состоящее из некоторой переменной или константы, которая добавляется к соответствующему смещению имени переменной. Таким образом можно обращаться к полям составной переменной (например, можно обеспечить доступ к полям сложной переменной, например, структуры).

Адрес любой ячейки состоит из двух компонентов: сегментного адреса и смещения. Сегментные же адреса хранятся в сегментных регистрах: DS, ES, CS и

SS. Процессор узнает, из какого регистра взять сегментный адрес с помощью префиксов замены сегмента (Имеется несколько групп префиксов: повторения, размера адреса, размера операнда, замены сегмента.)

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

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

Однако в ряде случаев префикс замены сегмента должен указываться в программе в явной форме. Такая ситуация возникает, например, если данные расположены в сегменте команд, что типично для резидентных обработчиков прерываний. Для обращения к таким данным можно, конечно, использовать регистр DS, если предварительно настроить его на сегмент команд, но проще выполнить адресацию через регистр CS, который и так уже настроен должным образом. Если в сегменте команд содержится поле данных с именем mem, то команда чтения из этого поля будет выглядеть следующим образом: mov АХ,С S:mem1

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

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

mov AX,0B800h ;Сегментный адрес видеобуфера

mov ES,AX ;Отправим его в ES

mov byte ptr ES: 0, ‘ ! ‘ ;Отправим символ на 1-е

mov byte ptr ES:2, ‘ ! ‘ ;Отправил символ на 2-е

Заметим, что команда mov ES:0,’!’

вызовет ошибку трансляции, так как ассемблер не сможет определить, надо ли транслировать это предложение, как команду пересылки в видеобуфер байта 21h, или как команду пересылки слова 0021h.

При необходимости можно было воспользоваться для записи в видеобуфер регистром DS:

mov AX ,0B800h ;Сегментный адрес

mov DS, AX ;видеобуфера в DS

mov byte ptr DS:0,’!’ ;Символ в видеобуфер

В код команды префикс замены сегмента не включается, но запись DS: необходима,

так как при записи mov 6,10 . будет ошибка (переслать число 10 в число 6),

команда mov DS:6,10 пересылает число 10 по относительному адресу 6, что имеет смысл.

При косвенной адресации смещение соответствующего операнда в сегменте содержится в одном из регистров микропроцессора. Таким образом, текущее содержимое регистра микропроцессора определяет исполнительный адрес того операнда, который будет использоваться в команде.

Синтаксически в команде этот режим адресации выражается заключением имени регистра в квадратные скобки [ ].

команда mov ax,[ecx] помещает в регистр ах содержимое слова по адресу из сегмента данных со смещением, хранящимся в регистре есх.

Косвенной адресации для микропроцессора 18086 можно использовать только регистры [ВХ], [SI], [DI], [ВР]. Для первых трех регистров их содержимое является смещением по отношению к сегменту данных (т.е. текущее значение сегментного регистра DS определяет вторую составляющую адреса). Регистр [ВР] определяет смещение в сегменте стека (текущее содержимое сегментного регистра SS) для вычисления адреса. При использовании регистров ВХ или ВР адресацию называют базовой, при использовании регистров SI или DI — индексной.

Преобразуем приведенный выше пример, чтобы продемонстрировать использование косвенной адресации через регистр.

mov AX,OB800h ;Сегментный адрес

mov ES, AX ; видеобуфера в ES

mov BX,2 0 0 0 ; Смещение к середине экрана

mov byte ptr ES : [BX] , ‘!’ ; Символ на экран

Если косвенная адресация осуществляется через один из регистров ВХ, SI или DI, то подразумевается сегмент, адресуемый через DS, поэтому при адресации через этот регистр обозначение DS: можно опустить: mov AX, 0B800h ; Сегментный адрес

mov DS, AX ;Видеобуфера в DS

mov BX, 2000 ; Смещение к середине экрана

mov byte ptr [BX] , ‘ ! ‘ ;Символ на экран

Этот фрагмент немного эффективнее предыдущего в смысле расходования памяти. Из-за отсутствия в коде последней команды префикса замены сегмента он занимает на 1 байт меньше места.

Регистры ВХ, SI и DI в данном применении совершенно равнозначны, и с одинаковым успехом можно воспользоваться любым из них: mov D1, 2 000 ;Смещение к середине экрана

mov byte ptr [DI] , ‘ ! ‘ ; Символ на экран

Не так обстоит дело с регистром ВР. Этот регистр специально предназначен для работы со стеком, и при адресации через этот регистр в режимах косвенной адресации подразумевается сегмент стека; другими словами, в качестве сегментного регистра по умолчанию используется регистр SS.

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

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

Для микропроцессоров старше I80386 косвенная индексная адресация и косвенная адресация по базе расширена. В качестве индексных регистров можно использовать все регистры данных — ([ЕАХ], [ЕВХ], [ЕСХ], [EDX]), а так же три индексных регистра — ([ЕВР], [ESI], [ED1]). В этом случае константа может быть или байтом, или двойным словом, и эта константа рассматривается как число со знаком.

Для всех регистров, кроме [ЕВР], при расчете адреса используется текущее содержимое сегментного регистра DS, а для регистра [ЕВР] -содержимое сегментного регистра SS.

Регистровая косвенная адресация со сдвигом (базовая и индексная). Относительный адрес операнда определяется, как сумма содержимого регистра ВХ, ВР, SI или DI и указанной в команде константы, называемой сдвигом, смещением или перемещением. Сдвиг может быть числом или адресом. Так же, как и в случае базовой адресации, при использовании регистров ВХ, SI и DI подразумевается сегмент, адресуемый через DS, а при использовании ВР подразумевается сегмент стека и, соответственно, регистр SS.

Рассмотрим применение косвенной адресации со смещением на примере прямого вывода в видеобуфер.

mov AX,0B800h ;Сегментный адрес

mov ES, АХ ; видеобуфера в ES

mov DI, 80*2*24 ;Смещение к нижней строке

mov byte ptr ES: [DI] , ‘О’ ;Символ на экран mov byte ptr ES: 2 [DI] , ‘К’ ;Запишем символ в следующую позицию

mov byte ptr ES : 4 [DI], ‘! ‘ ;Запишем символ в следующую позицию В этом примере в качестве базового выбран регистр DI; в него заносится базовый относительный адрес памяти, в данном случае смещение в видеобуфере к началу последней строки экрана. Модификация этого адреса с целью получить смещение по строке экрана осуществляется с помощью констант 2 и 4,

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

Вместо, 4[ВХ] можно с таким же успехом написать [ВХ+4], 4+[ВХ] или [BX]+4.

Рассмотрим пример, когда сдвиг задается адресом массива, а в регистре находится индекс адресуемого элемента в этом массиве. Пусть надо заполнить массив из 10000 слов натуральным рядом чисел.

;Сегмент данных array dw 10000 dup(0)

mov S1, 0 Начальное значение индекса элемента в

mov AX, 0 ;Первое число-заполнитель

mov СХ,10000 ; Число шагов в цикле (всегда в СХ)

fill: mov array[SI],AX ;Занесение числа в элемент массива

inc AX Инкремент числа-заполнителя

add SI, 2 ;Смещение в массиве к следующему слову

loop fill ;Возврат на метку fill (СХ раз)

Цикл начинается с команды, помеченной меткой fill (правила образования имен меток такие же, как и для имен полей данных). В этой команде содержимое АХ, сначала равное 0, переносится в ячейку памяти, адрес которой вычисляется, как сумма адреса массива array и содержимого индексного регистра SI, в котором в первом шаге цикла тоже 0. В результате в первое слово массива заносится 0. Далее содержимое регистра АХ увеличивается на 1, содержимое регистра SI — на 2 (из-за того, что массив состоит из слов), и командой loop осуществляется переход на метку fill, после чего тело цикла повторяется при новых значениях регистров АХ и SI. Число шагов в цикле, отсчитываемое командой loop, определяется исходным содержимым регистра СХ.

Базово-индексная адресация. Относительный адрес операнда определяется, как сумма содержимого следующих пар регистров:

Относительный (эффективный ) адрес операнда определяется как сумма содержимого следующих пар регистров.

[ВХ] [SI] (подразумевается DS : [ВХ] [SI])

[ВХ] [DI] (подразумевается DS:[BX][DI])

[ВР] [SI] (подразумевается SS:[BP][SI])

[ВР] [DI] (подразумевается SS:[BP][DI])

В одном из регистров находится, как правило адрес массива, а в другом — индекс.

Рассмотрим предыдущий пример с введением в него базово-индексной адресации .

array dw 10000 dup(0)

mov BX,offset array ;Базовый адрес массива в ;базовом регистре

mov SI, 0 ;Начальное значение индекса ;элемента в массиве


mov AX, 0 ;Первое число-заполнитель

mov CX,10000 ; Число шагов в цикле

fill: mov [BX][SI],AX ; Отправим число в массив

inc AX Инкремент числа-заполнителя

add SI, 2 ; Смещение в массиве к следующему слову

loop fill ;На метку fill (CX раз)

Повышение эффективности достигается за счет того, что команда занесения числа в элемент массива оказывается короче (так как в нее не входит адрес массива) и выполняется быстрее, так как этот адрес не надо каждый раз считывать из памяти.

Базово-индексная адресация со сдвигом. Относительный адрес операнда определяется как сумма содержимого двух регистров и сдвига

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

Пусть в сегменте данных определен массив из 24 байтов, в котором записаны коды латинских и русских символов верхнего ряда клавиатуры: sims db ” QWERTYUIOP<>”

Последовательность команд mov BX,12 ; Число байтов в строке

загрузит в регистр DL элемент с индексом 6 из второго ряда, т.е. код ASCII буквы Г. Тот же результат можно получить, загрузив в один из регистров не индекс, а адрес массива:

mov BX, offset sym

Косвенная адресация с масштабированием (микропроцессор I80386 и старше)

Еще одна дополнительная возможность косвенной адресации используется в микропроцессорах I80386 и старше — при индексной адресации (простой и адресации по базе с индексированием) содержимое индексного регистра ([ЕАХ], [ЕВХ], [ЕСХ], [EDX], [EBP], [ESI], [EDI]) можно дополнительно умножить на масштабный множитель -число 1, 2, 4, 8. (Использование множителя 1 соответствует обычной индексной адресации). Такой подход позволяет упростить доступ к элементам массива, имеющих элементы, кратные множителю (например, к элементам массивов, состоящим

из слов и двойных слов). В таких случаях в индексный регистр просто записывается номер элемента и указывается необходимый множитель. Основная литература:5[125-135],7[74-82],4[98-110], Дополнительная литература: 18[113-118]. Контрольные вопросы: 1 Какие три основные директивы ассемблера используются для определения данных ?. 2. Как описать строку в ассемблере? 3. На какие типы делятся все обращения к данным? 4. Назовите основные виды адресации операндов в памяти. 5. Какие способы адресации удобно использовать для работы с массивами? Тема лекции 5. Команды микропроцессора. Классификация. Группа команд пересылки данных. Система команд микропроцессора содержит около 130 машинных команд. С появлением каждой новой модели микропроцессора их количество, как правило, возрастает.Классификация команд представлена на рисунке 2.

Пересылки Арифметичес Логические Передачи Цепочечные Управления
данных кие управления состоянием
ЦП
Команды ассемблера

Общего назначения

Двоичной арифметики

Манипуляции битами

Безусловные

Десятичной арифметики

Рисунок 2. Машинные команды и их функциональные группы Группа команд пересылки данных. Включает 1. команды пересылки данных 2. команды ввода-вывода в порт;
Условные

Работы со стеком

Сдвига

Преобразование типов

1. команды работы с адресами и указателями;

2. команды преобразования данных;

3. команды работы со стеком.

Команды пересылки данных

К этой группе относятся следующие команды: mov , xchg ,

По команде mov на место первого операнда пересылается значение второго операнда. Флаги эта команда не меняет.

mov АХ,500 ; АХ :=500 mov BL,DH ; BL:=DH

Требование: необходимо следить, чтобы размерности (типы) пересылаемых операндов соответствовали друг другу.

1 пересылать из одной области памяти в другую;

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

1. загрузить в сегментный регистр значение непосредственно из памяти (нужно использовать промежуточный объект: регистр общего назначения или стек.)

2. переслать содержимое одного сегментного регистра в другой сегментный регистр. Это объясняется тем, что в системе команд нет соответствующего кода операции. Но необходимость в таком действии часто возникает. Выполнить такую пересылку можно, используя в качестве промежуточных все те же регистры общего назначения. Вот пример инициализации регистра es значением из регистра ds:

mov ax, ds mov es,ax

Но есть и другой, более красивый способ выполнения данной операции — использование стека и команд push и pop:

push ds ; поместить значение регистра ds в стек pop es ;записать в es число из стека

3. нельзя использовать сегментный регистр cs в качестве операнда назначения, так как пара cs:ip всегда содержит адрес команды, которая должна выполняться следующей. Изменение командой mov содержимого регистра cs фактически означало бы операцию перехода, а не пересылки, что недопустимо.

Как известно, в ПК числа размером в слово хранятся в памяти в «перевернутом» виде, а в регистрах — в нормальном, неперевернутом. Команда MOV учитывает это и при пересылке слов между памятью и регистрами сама «переворачивает» их:

Q dw 1234h ; Q: 34h, Q+l: 12h MOV AX, Q. ; AH-12h, AL-34h Пусть имеются такие описания переменных X DB ?

Как правило, в команде MOV легко узнается тип (размер) одного из операндов, он и определяет размер пересылаемой величины. Например:

MOV ВН, 0; пересылка байта (ВН — байтовый регистр)

MOV х, 0 ; то же самое (X описан как имя байтовой переменной)

MOV SI, 0 ; пересылка слова (SI — регистр размером в слово)

MOV Y, 0 ; то же самое (Y описан как имя переменной-слова)

Отметим, что здесь по второму операнду (0) нельзя определить, какого он размера: ноль может быть и байтом (00h), и словом (0000h).

Если можно определить размеры обоих операндов, тогда эти размеры должны совпадать (либо байты, либо слова), иначе ассемблер зафиксирует ошибку. Например:

MOV DI, ES ; пересылка слова

MOV СН, Х ; пересылка байта

MOV DX, AL ; ошибка (DX — слово, AL — байт)

MOV BH, 300 ; ошибка (ВН — байт, а 300 не может быть байтом)

Необходимо использовать оператор ptr во всех сомнительных относительно согласования размеров операндов случаях.

mov ax, word ptr [bx] ;если [Ьх] адресует слово в памяти inc byte ptr [bx] ; если [bx] адресует байт в памяти dec dword ptr [bx] ;если [bx] адресует двойное слово в памяти mov word ptr [bx],0 ;если [bx] адресует слово в памяти (PTR (от pointer, указатель) записывается следующим образом:

где • это BYTE, WORD или DWORD (есть и другие варианты), а выражение может быть константным или адресным.

Если указано константное выражение, то оператор «говорит», что значение этого выражения (число) должно рассматриваться ассемблером как величина указанного типа (размера); например, BYTE PTR 0 — это ноль как байт, a WORD PTR 0 — это ноль как слово (запись BYTE PTR 300 ошибочна, т. к. число 300 не может быть байтом). Отметим, что в этом случае оператор PTR относится к константным выражениям.

Если же в PTR указано адресное выражение, то оператор «говорит», что адрес, являющийся значением выражения, должен восприниматься ассемблером как адрес ячейки указанного типа (размера); например: WORD PTR A — адрес А обозначает слово (байты с адресами А и А+1). В данном случае оператор PTR относится к адресным выражениям.

Также этот оператор нужно применять, когда требуется принудительно поменять размерность операндов. Например, требуется переслать значение 0ffh во второй байт поля flp:

mov byte ptr (flp+1), 0ffh

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

Команды ввода-вывода в порт

Операнды машинной команды могут находиться в портах ввода-вывода. Каждое устройство ввода/вывода, каждое системное устройство имеет один или несколько регистров, доступ к которым осуществляется через адресное пространство ввода/вывода. Эти регистры имеют разрядность 8, 16 или 32 бит. Адресное пространство ввода/вывода физически независимо от пространства оперативной памяти и имеет ограниченный объем, составляющий 2 16 , или 65536 адресов ввода/вывода. Таким образом, понятие порта ввода-вывода можно определить как 8, 16 или 32-разрядный аппаратный регистр, имеющий определенный адрес в адресном пространстве ввода/вывода. Вся работа системы с устройствами на самом низком уровне выполняется с использованием портов ввода-вывода. Упрощенная, концептуальная схема управления оборудованием компьютера имеет вид:

Рисунок3. Концептуальная схема управления оборудованием компьютера

Для работы с портами используются две команды : in и out .

in аккумулятор, номерпорта — ввод в аккумулятор из порта с номером номер_ порта;

out порт, аккумулятор — вывод содержимого аккумулятора в порт с номером номер_ порта.

Команды работы со стеком

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

Для работы со стеком предназначены три регистра: ss — сегментный регистр стека; sp/esp — регистр указателя стека;

bp/ebp — регистр указателя базы кадра стека.

Размер стека зависит от режима работы микропроцессора и ограничивается 64 Кбайт (или 4 Гбайт в защищенном режиме).

Особенности работы со стеком:

— запись и чтение данных в стеке осуществляется в соответствии с принципом LIFO (Last In First Out — «последним пришел, первым ушел»);

— по мере записи данных в стек последний растет в сторону младших адресов. Эта особенность заложена в алгоритм команд работы со стеком;

— при использовании регистров esp/sp и ebp/bp для адресации памяти ассемблер автоматически считает, что содержащиеся в нем значения представляют собой смещения относительно сегментного регистра ss.

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

push источник — запись значения источник в вершину стека. алгоритм работы этой команды:

1) (sp) = (sp) — 2; значение sp уменьшается на 2;

pop назначение — запись значения из вершины стека по месту, указанному операндом назначение. Значение при этом «снимается» с вершины стека

2) -значение из источника записывается по адресу, указываемому парой ss:

pop назначение — запись значения из вершины стека по месту, указанному операндом назначение. Значение при этом «снимается» с вершины стека алгоритм работы этой команды:

1) запись содержимого вершины стека по месту, указанному операндом назначение

2 )(sp) = (sp) + 2; увеличение значения sp.

Основная литература :5[129-152],9[42-46]

Дополнительная литература: 19[78-88].

1. Приведите классификацию команд ассемблера.

2. Перечислите команды, входящие в группу пересылки данных.

3. Назовите команды пересылки для работы со стеком.

4. Какой оператор необходимо использовать во всех сомнительных отно­сительно согласования размеров операндов случаях.

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: На стипендию можно купить что-нибудь, но не больше. 8992 — | 7238 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Please verify you are a human

Access to this page has been denied because we believe you are using automation tools to browse the website.

This may happen as a result of the following:

  • Javascript is disabled or blocked by an extension (ad blockers for example)
  • Your browser does not support cookies

Please make sure that Javascript and cookies are enabled on your browser and that you are not blocking them from loading.

Reference ID: #91b7fae0-0652-11ea-8239-0b7ee27910f4

Версии ассемблеров

Microsoft Macro Assembler (MASM)

MASM — ассемблер для процессоров семейства x86. Первоначально был произведён компанией Microsoft для написания программ в операционной системе MS-DOS и был в течение некоторого времени самым популярным ассемблером, доступным для неё. Это поддерживало широкое разнообразие макросредств и структурированность программных идиом, включая конструкции высокого уровня для повторов, вызовов процедур и чередований (поэтому MASM — ассемблер высокого уровня). Позднее была добавлена возможность написания программ для Windows. MASM — один из немногих инструментов разработки Microsoft, для которых не было отдельных 16- и 32-битных версий.

В начале 1990-х годов альтернативные ассемблеры, вроде Borland TASM и свободного ассемблера NASM, начали отбирать часть доли рынка MASM. Однако два события в конце 1990-х позволили MASM сохранить большую часть своей доли: сначала Microsoft прекратила продавать MASM как коммерческий продукт. Во-вторых, благодаря пакету MASM32 оказалось, что программирование на MASM возможно и в среде Microsoft Windows. В 2000 году MASM 6.15 был выпущен как часть пакета разработки Visual C++ и все версии Visual C++ после 6.0 включали в себя версию MASM, равную версии Visual C++. Позже в Visual C++ 2005 появилась 64-битная версия MASM. Вместе с большим сообществом программистов MASM эти события помогли остановить снижение популярности MASM по сравнению с другими ассемблерами. Сегодня MASM продолжает использоваться на платформе Win32, несмотря на конкуренцию с новыми продуктами, такими как NASM, FASM, TASM, HLASM.

Есть много развивающихся проектов для разработки программного обеспечения, которые поддерживают MASM, включая интегрированные среды разработки (ИСР), например RadASM.

Версии MASM. Хотя MASM больше не является коммерческим продуктом, Microsoft продолжает поддерживать исходный код, используемый и в других продуктах Microsoft. С тех пор как Microsoft прекратила продавать MASM отдельно, было выпущено несколько обновлений к производственной линии MASM 6.x (последнее обновление — версия 6.15, которая была включена в Visual C++ 6.0), а после этого — MASM 7.0 в составе Visual C++ .NET 2002, MASM 7.1 в составе Visual C++ .NET 2003, MASM 8.0 в составе Visual C++ 2005 и MASM 9.0 в составе Visual C++ 2008, поддерживающие платформу x64.

Flat assembler (FASM)

FASM- свободно распространяемый многопроходной ассемблер, написанный Томашем Грыштаром (польск.Tomasz Grysztar). FASM написан на самом себе, обладает небольшими размерами и очень высокой скоростью компиляции, имеет богатый и ёмкий макро-синтаксис, позволяющий автоматизировать множество рутинных задач. Поддерживаются как объектные форматы, так и форматы исполняемых файлов. Это позволяет в большинстве случаев обойтись без компоновщика. В остальных случаях нужно использовать сторонние компоновщики, поскольку таковой вместе сFASMне распространяется.

Компиляция программы в FASMсостоит из 2 стадий: препроцессирование и ассемблирование. На стадии препроцессора раскрываются все макросы, символические константы, обрабатываются директивы препроцессора. В отличие от стадии ассемблирования, препроцессирование выполняется только 1 раз. Смешивание стадий ассемблирования и препроцессирования — распространённая ошибка начинающих.

На стадии ассемблирования определяются адреса меток, обрабатываются условные директивы, раскрываются циклы и генерируется собственно программа. FASM— многопроходной ассемблер, что позволяет ему делать некоторую оптимизацию, например, генерирование короткого перехода на метку вместо длинного. Во время прохода компилятор не всегда может вычислить выражение в условных директивах. В этом случае он делает какой-нибудь выбор и пытается скомпилировать дальше. Благодаря тому, что адреса меток, вычисленные на N-ном проходе, используются на N+1-проходе, этот процесс обычно сходится.

Используется Intel-синтаксисзаписи инструкций. Единственное существенное отличие от формата, принятого в других ассемблерах (MASM, TASM в режиме совместимости с MASM) — значение ячейки памяти всегда записывается в квадратных скобках -[label_name], а простоlabel_nameозначает адрес (то есть порядковый номер) ячейки. Это позволяет обходиться без ключевого словаoffset. Также в FASM при переопределении размера операнда вместоbyte ptrпишется простоbyte, вместоword ptr—wordи т. д. Не позволяется использовать несколько квадратных скобок в одном операнде, таким образом вместо[bx][si]необходимо писать[bx+si]. Эти изменения синтаксиса привели к более унифицированному и лёгкому для чтения коду.

Использование FASMподдерживают многие специализированные ИСР, такие как RadASM, WinAsm Studio, Fresh (IDE) (специально спроектированный под FASM) и т. д.

NASM (Netwide Assembler)

NASM —свободный(LGPLилицензия BSD)ассемблердля архитектурыIntelx86. Используется для написания 16-, 32- и 64-битных программ.

NASM был создан Саймоном Тэтхемом совместно с Юлианом Холлом и в настоящее время развивается небольшой командой разработчиков на SourceForge.net. Первоначально он был выпущен согласно его собственной лицензии, но позже эта лицензия была заменена на GNU LGPL после множества проблем, вызванных выбором лицензии. Начиная с версии 2.07 лицензия заменена на «упрощённую BSD» (BSD из 2 пунктов).

NASM может работать на платформах, отличных от x86, таких как SPARC и PowerPC, однако код он генерирует только для x86 и x86-64.

NASM успешно конкурирует со стандартным в Linux- и многих других UNIX-системах ассемблером gas. Считается, что качество документации у NASM выше. Кроме того, ассемблер gas по умолчанию [5] использует AT&T-синтаксис, ориентированный на процессоры не от Intel, в то время как NASM использует вариант традиционного для x86-ассемблера Intel-синтаксиса; Intel-синтаксис используется всеми ассемблерами для Windows-систем, например MASM, TASM, FASM.


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

Компиляция программ в NASM состоит из двух этапов. Первый — ассемблирование, второй — компоновка. На этапе ассемблирования создаётся объектный код. В нём содержится машинный код программы и данные, в соответствии с исходным кодом, но идентификаторы (переменные, символы) пока не привязаны к адресам памяти. На этапе компоновки из одного или нескольких объектных модулей создаётся исполняемый файл (программа). Операция компоновки связывает идентификаторы, определённые в основной программе, с идентификаторами, определёнными в остальных модулях, после чего всем идентификаторам даются окончательные адреса памяти или обеспечивается их динамическое выделение.

Для компоновки объектных файлов в исполняемые в Windows можно использовать свободный бесплатно распространяемый компоновщик alink, а в Linux — компоновщик ld, который есть в любой версии этой операционной системы.

В NASM используется Intel-синтаксис записи инструкций.

Turbo Assembler (TASM)

TASM— программный пакет компании Borland, предназначенный для разработки программ на языке ассемблера для архитектуры x86. Кроме того, TASM может работать совместно с трансляторами с языков высокого уровня фирмы Borland, такими как Turbo C и Turbo Pascal. Как и прочие программные пакеты серии Turbo, Турбо Ассемблер больше не поддерживается.

TASM до сих пор используется для обучения программированию на ассемблере под архитектуру x86. Многие находят его очень удобным и продолжают его использовать, расширяя набором дополнительных макросов.

Пакет TASM поставляется вместе с компоновщиком Turbo Linker и порождает код, который можно отлаживать с помощью Turbo Debugger.

По умолчанию TASM работает в режиме совместимости с другим распространённым ассемблером — MASMi, то есть TASM умеет транслировать исходники, разработанные под MASM. Кроме того, TASM имеет режим IDEAL, улучшающий синтаксис языка и расширяющий его функциональные возможности.

GoAsm — ассемблер для процессоров семейства x86, созданный Джереми Гордоном (англ. Jeremy Gordon) для написания программ для операционных систем семейства Windows, способен создавать 32- и 64-битных версий, а также программы с поддержкой Unicode. GoAsm является проприетарным ПО и распространяется в бинарном формате.

GoAsm создавался с целью создать компилятор с простым и ясным синтаксисом, производящий как можно более компактный код, скромными потребностями для обработки скриптов и возможностью добавления расширений. Особенности:

GoAsm не создаёт 16-разрядный код и способен работать только в «плоском» режиме (без сегментов), благодаря этому синтаксис очень прост.

В качестве формата выходных данных используется COFF (Portable Executable format), и для создания исполняемых файлов необходимо использовать дополнительный компоновщик (например— GoLink или ALINK) и компилятор ресурсов (GoRC).

GoAsm способен файлы в формате Unicode (UTF-16 или UTF-8).

Несмотря на то что используется Intel-синтаксис, синтаксис GoAsm несовместим ни с одним из существующих компиляторов. GoAsm использует препроцессор сходный по синтаксису с препроцессором языка программирования C. В GoAsm необходимо использовать квадратные скобки для чтения и записи памяти. Для того чтобы получить смещение необходимо записать:

Язык программирования ассемблер

Ассемблер как язык программирования низкого уровня, представляющий собой формат записи машинных команд, удобный для восприятия человеком. Программирование на языке ассемблер: преимущества и недостатки языка. Turbo Assembler, система прерывания программ.

Рубрика Программирование, компьютеры и кибернетика
Вид реферат
Язык русский
Дата добавления 18.12.2013
Размер файла 110,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

язык программирование ассемблер

Язык программирования ассемблер

Программирование на языке ассемблер

Преимущества и недостатки языка

Turbo Assembler (TASM)

Система прерывания программ

Работа механизма прерывания

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

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

1. На других языках программирования не всегда возможно написать приложение, которое полно бы удовлетворяло требованиям. А в некоторых случаях полностью невозможно. На языке программирования Ассемблер можно написать любое приложение.

2. Иногда языки программирования высокого уровня не могут обеспечить требуемое быстродействие. А приложение созданное на Ассемблере всегда быстродействующее.

3. Размер приложений созданных на языках высокого уровня имею гораздо больший размер, чем приложения созданные на Ассемблере.

4. Язык Ассемблер позволяет работать непосредственно с аппаратными средствами, что в некоторых случаях дает программисту преимущество и требуемый результат. Приложение на языке высокого уровня работает с аппаратными устройствами через написанные модули, т. е. не позволит программисту что-либо изменить, а, следовательно, получить требуемый результат.

5. Знание языка Ассемблер дает большее преимущество перед теми, кто программирует только на языках высокого уровня. Знающий Ассемблер знает и структуру компьютера, и структуру аппаратных устройств.

описать язык программирования Ассемблер;

выявить преимущества и недостатки языка;

описать Turbo Assembler;

ознакомиться с механизмом прерывания.

Язык программирования ассемблер

Программисты уже были знакомы с понятием подпрограммы: Грейс Хоппер и ее коллеги применяли подпрограммы на гарвардском «Марке-1» во время второй мировой войны, однако каждая подпрограмма решала свою специфическую задачу.

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

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

Морис Уилкс назвал мнемоническую схему для «Эдсака» и библиотеку подпрограмм собирающей системой (по-английски assembly system — отсюда слово «ассемблер»), поскольку она собирала последовательности подпрограмм.

Ассеммблер (от англ. assembler — сборщик) — компьютерная программа, компилятор исходного текста программы, написанной на языке ассемблера, в программу на машинном языке. [2]

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

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

Программирование на языке ассемблер

Ассемблер — язык программирования низкого уровня, представляющий собой формат записи машинных команд, удобный для восприятия человеком. [3]

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

Директивы ассемблера позволяют включать в программу блоки данных (описанные явно или считанные из файла) ; повторить определённый фрагмент указанное число раз; компилировать фрагмент по условию; задавать адрес исполнения фрагмента, менять значения меток в процессе компиляции; использовать макроопределения с параметрами и др.

Каждая модель процессора, в принципе, имеет свой набор команд и соответствующий ему язык (или диалект) ассемблера. [4]

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

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

Ясно, что эффективность и точность языка Ассемблера дают определенные преимущества. Но его детализированность создает и некоторые проблемы. Когда же стоит выбирать для программирования язык Ассемблера?

Конечно, вы должны пользоваться программами на языке Ассемблера, когда нет другого способа написать программу. Например, программисты фирмы IBM писали с использованием процедур Ассемблера все программы управления устройствами ввода-вывода для IBM PC. Для управления устройствами ввода-вывода и системой прерываний, потребовалась та точность языка Ассемблера, которую не может обеспечить ни один другой язык программирования. Аналогично, на языке Ассемблера в фирме IBM писались процедуры диагностики, которые должны проверять каждую деталь аппаратуры.

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

Какая программа не подходит для языка Ассемблера? Конечно, вы можете написать на нем любую программу, однако с большой программой лучше работать в языке высокого уровня, таком как C или C#. Эти языки позволяют вам сосредоточиться на своей проблеме. Вам не приходится непосредственно иметь дело с тонкостями аппаратного оборудования и процессора. Языки высокого уровня позволяют вам отступить назад и за деревьями увидеть лес.

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

Самыми популярными на сегодняшний день являются пакеты Turbo Assembler (TASM) фирмы Borland, Macro Assembler for Windows32 (MASM32), созданный Hutch (на основе старого MASM фирмы Microsoft), а также Flat Assembler (FASM), и Netwide Assembler (NASM), развиваемый командой NASM Development Team. Все эти ассемблеры предоставляют весьма широкие возможности для программиста. На них можно писать программы как под DOS, так и под Windows.

Существует также множество других видов ассемблера, число которых растет. Например: CodeX Assembler, Gema Assembler, Light Macro Assembler (LASM), Lazy Assembler (LZASM), Table Driven Assembler (TDASM), NewBasic++ Assembler (NBASM), TMA Macro Assembler и др. [5]

Преимущества и недостатки языка

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

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

При программировании на ассемблере возможен непосредственный доступ к аппаратуре, в том числе портам ввода-вывода, регистрам процессора, и др.

Язык ассемблера применяется для создания драйверов оборудования и ядра операционной системы

Язык ассемблера используется для создания «прошивок» BIOS.

С помощью языка ассемблера создаются компиляторы и интерпретаторы языков высокого уровня, а также реализуется совместимость платформ.

+ Существует возможность исследования других программ с отсутствующим исходным кодом с помощью дизассемблера.

Главное преимущество ассемблера практически полностью нивелируется хорошей оптимизацией в современных компиляторах языков высокого уровня.

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

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

Отсутствует переносимость программ на компьютеры с другой архитектурой и системой команд (кроме двоично-совместимых). [4]

Турбо Ассемблер фирмы Borland представляет собой многопроходный ассемблер с разрешением опережающих ссылок, скоростью ассемблирования до 48000 строк в минуту (на компьютере IBM PS/2, модель 60), совместимый с макроассемблером фирмы Microsoft MASM и дополнительной возможностью использования режима расширенного синтаксиса. Независимо от вашего опыта в программировании вы, несомненно, оцените эти особенности, а также ряд других средств, которые значительно облегчают программирование на Ассемблере.

Среди таких средств можно кратко упомянуть следующие:

полная поддержка процессора 80386;

улучшенная синтаксическая проверка типов;

упрощенные директивы определения сегментов;

улучшенное управление листингом;

расширения инструкций POP и PUSH;

расширенный оператор CALL с аргументами и необязательным параметром языка;

локальные идентификаторы в стеке и аргументы вызова в процедурах;

структуры и объединения;

режим QUIRK, эмулирующий MASM;

полная отладка на уровне исходного текста с помощью Турбо отладчика;

встроенная утилита генерации перекрестных ссылок (TCREF) ;

файлы конфигурации и командные файлы. [6]

Турбо Ассемблер является мощным Ассемблером, работающим с командной строкой, который воспринимает ваши исходные файлы (файлы с расширением *. asm*) и создает из них объектные модули (файлы с расширением *. obj*). После этого вы можете использовать программу-компоновщик фирмы Borland TLINK. EXE, отличающуюся высокой скоростью компоновки, для компоновки полученных объектных модулей и создания выполняемых файлов (файлов с расширением *. exe*).

Турбо Ассемблер создан для работы с процессорами серии 80х86 и 80х87 (более подробно набор инструкций процессоров серии 80х86/80х87 описан в соответствующих руководствах фирмы Intel).

Turbo Assembler, помимо полной поддержки транслятора фирмы Microsoft имеет дополнительные возможности, объединённые в режиме, названном разработчиками Ideal. Использование этого режима даёт возможность начинающему программисту применять более наглядный и простой стиль разработки программ. Более опытные программисты, пишущие на ассемблере, могут использовать такие возможности режима Ideal, как вложенные структуры, объединения.

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

— возможность использования одинаковых имён для обозначения членов различных структур;

— применение операторов HIGH и LOW;

— предварительное вычисление выражений EQU;

— корректное управление сегментами данных объединённых в группы;

— усовершенствованное использования директив;

— разумное использование скобок в выражениях.

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

Традиционным способом, с помощью которого объединяются программы, написанные на С++ и Ассемблере, является разделительная компиляция с последующей компоновкой в один исполняемый файл. При этом можно использовать компилятор Borland C++, который вызывает Turbo Assembler для трансляции ассемблерной программы. [7]

Разработка программы на языке Turbo Assembler включает четыре этапа:

1-й этап. Подготовка исходного текста программы и оформление его в виде текстового файла (одного или нескольких) с помощью какого-нибудь редактора в формате DOS с расширением *. asm*.

2-й этап. Ассемблирование программы с применением транслятора Tasm, результатом которого является объектный файл с расширением *. obj*. Когда программа состоит из нескольких файлов (модулей), то их ассемблирование производится независимо друг от друга. Если в процессе трансляции будут обнаружены ошибки, то объектный файл не создаётся, а формируется сообщение об ошибках. Ошибки устраняются, после чего трансляция повторяется. Объектный файл (двоично-кодированное представление программы) не может быть запущен на исполнение, так как в нём не содержится информация о загрузке сегментов программы в памяти компьютера.

3-й этап. Компоновка программы производится компоновщиком (редактором связей) Turbo Linker и заключается в объединении объектных модулей в один исполняемый файл с назначением стартового адреса программы. Исполняемый файл имеет расширение *. exe*. 2-й и 3-й этапы определяют процесс подготовки исполнительного файла программы, называемого трансляцией.

4-й этап состоит в отладке программы с использованием отладчика Turbo Debugger, который будет являться основным инструментом при изучении форматов команд, их кодирования, а также представления переменных программы в памяти.

Система прерывания программ

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

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

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

Прерывание (англ. interrupt) — сигнал, сообщающий процессору о наступлении какого-либо события. При этом выполнение текущей последовательности команд приостанавливается, и управление передаётся обработчику прерывания, который реагирует на событие и обслуживает его, после чего возвращает управление в прерванный код. [3]

Программное прерывание — синхронное прерывание, которое может осуществить программа с помощью специальной инструкции. [5]


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

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

Программы могут сами вызывать прерывания с заданным номером. Для этого они используют команду INT. Это так называемые программные прерывания. Программные прерывания не являются асинхронными, так как вызываются из программы.

В процессорах архитектуры x86 для явного вызова синхронного прерывания имеется инструкция Int, аргументом которой является номер прерывания (от 0 до 255). ВIBM PC-совместимых компьютерах обработку некоторых прерываний осуществляют подпрограммы BIOS, хранящиеся в ПЗУ, и это служит интерфейсом для доступа к сервису, предоставляемому BIOS. Также, обслуживание прерываний могут взять на себя BIOS карт расширений (например, сетевых или видеокарт), операционная система и даже обычные (прикладные) программы, которые постоянно находятся в памяти во время работы других программ (т. н. резидентные программы). В отличие от реального режима, в защищённом режиме x86-процессоров обычные программы не могут обслуживать прерывания, эта функция доступна только системному коду (операционной системе).

MS-DOS использует для взаимодействия со своими модулями и прикладными программами прерывания с номерами от 20h до 3Fh (числа даны в шестнадцатеричной системе счисления, как это принято при программировании на языке ассемблера x86). Например, доступ к основному множеству функций MS-DOS осуществляется исполнением инструкции Int 21h (при этом номер функции и её аргументы передаются в регистрах). Это распределение номеров прерываний не закреплено аппаратно и другие программы могут устанавливать свои обработчики прерываний вместо или поверх уже имеющихся обработчиков, установленных MS-DOS или другими программами, что, как правило, используется для изменения функциональности или расширения списка системных функций. Также, этой возможностью пользуются вирусы. [8]

Работа механизма прерывания

Каждое определённое прерывание идентифицируется своим номером. Например, таймер и клавиатура и принтер имеют каждый свой собственный номер прерывания. Что касается базовой системы ввода/вывода, то её сервисные программы подразделяются на группы, причём за всеми программами группы закрепляется один номер прерывания.

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

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

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

Для примера рассмотрим программу, которая представляет собой исполняемый *. exe файл, после запуска которого на экране периодически появляется государственный флаг России. Период появлений примерно 1 раз в 2 секунды (см. Приложение). Данная программа имеет следующий алгоритм работы (рис. 1) :

Размещено на http://www.allbest.ru/

Рис. 1. Алгоритм работы программы.

Программное обращение к видеодрайверу BIOS реализуется с помощью прерывания INT 10h. При работе в текстовом режиме обычно используются следующие функции драйвера:

02h — установить позицию курсора;

03h — получить позицию курсора;

05h — установить видеостраницу;

06h — инициализировать или прокрутить вверх окно;

07h — инициализировать или прокрутить вниз окно;

08h — прочитать символ и атрибут в позиции курсора;

09h — вывести символ и атрибут в позицию курсора;

0Ah — вывести символ в позицию курсора;

0Eh — вывести символ в режиме телетайпа;

10h, подфункция 3h — переключить бит мерцание/яркость;

13h — вывести строку в режиме телетайпа. [10]

С помощью функций 06h и 07h в заданном месте экрана дисплея создаются цветные прямоугольные окна заданного размера. Если в эти окна выведен какой-либо текст, то с помощью этих функций его можно прокручивать вверх и вниз.

Функции 09h, 0Ah, 0Eh и 13h служат для вывода на экран отдельных символов и символьных строк (в цикле). Предусмотрен вывод одного и того же символа заданное число раз, что можно использовать при создании рамок и других орнаментов.

Функция 0Eh реагирует на управляющие коды, выполняя соответствующие действия. Курсор перемещается после вывода каждого символа.

Функция 13h предназначена для вывода строк с указанием атрибутов как каждого символа в отдельности, так и всей строки. Функция может выполняться в четырех вариантах в зависимости от кода режима, указываемого в регистре AL.

При выводе на экран средствами драйвера BIOS необходимо иметь в виду, что ввод с клавиатуры Ctrl/C не приводит к завершению программы. Следует опасаться бесконечных циклов вывода на экран — выход из них возможен только путем перезагрузки компьютера. [10]

Сигналы внешних аппаратных прерываний (от таймера, клавиатуры, дисков и проч.) поступают в процессор не непосредственно, а через контроллер прерываний, в качестве которого используется микросхема Intel 8259A. Обработка аппаратного прерывания обязательно включает в себя процедуры управления контроллером прерываний. Организация системы аппаратных прерываний заключается в том, что к восьми входным выводам контроллера подключаются выводы устройств, на которых возникают сигналы прерываний. Выход INT контроллера подключается к одноименному входу микропроцессора. При этом, кроме сигнала INT, инициирующего процедуру прерывания в микропроцессоре, контроллер передает в микропроцессор по линиям данных номер вектора, через который должна быть вызвана программа обработки поступившего прерывания. Передаваемый номер вектора образуется в контроллере путем сложения базового номера, записанного в одном из его регистров, с номером входной линии, по которой поступил запрос. Номер базового вектора заносится в контроллер автоматически в процессе начальной загрузки компьютера. Контроллер программируется через порты 20h и 21h. Поскольку базовый вектор всегда равен 8, то номера векторов, закрепленных за аппаратными прерываниями, лежат в диапазоне 8h. Fh.

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

Прерывания это готовые процедуры, которые компьютер вызывает для выполнения определенной задачи. Существуют аппаратные и программные прерывания. Аппаратные прерывания инициируются аппаратурой, либо с системной платы, либо с карты расширения. Они могут быть вызваны сигналом микросхемы таймера, сигналом от принтера, нажатием клавиши на клавиатуре и множеством других причин. Аппаратные прерывания не координируются с работой программного обеспечения. Когда вызывается прерывание, то процессор оставляет свою работу, выполняет прерывание, а затем возвращается на прежнее место. Для того чтобы иметь возможность вернуться точно в нужное, место программы, адрес этого места (CS: IP) запоминается на стеке, вместе с регистром флагов. Затем в CS: IP загружается адрес программы обработки прерывания и ей передается управление. Программы обработки прерываний иногда называют драйверами прерываний. Они всегда завершаются инструкцией IRET (возврат из прерывания), которая завершает процесс, начатый прерыванием, возвращая старые значения CS: IP и регистра флагов, тем самым, давая программе возможность продолжить выполнение из того же состояния. Все IBM PC используют микросхему таймера 8253 (или 8254) для согласования импульсов от микросхемы системных часов. Число циклов системных часов преобразуется в один импульс, а последовательность этих импульсов подсчитывается для определения времени, или они могут быть посланы на громкоговоритель компьютера для генерации звука определенной частоты. Микросхема 8253 имеет три идентичных независимых канала, каждый из которых может программироваться. Микросхема 8253 работает независимо от процессора. Процессор программирует микросхему и затем обращается к другим делам. Таким образом 8253 действует как часы реального времени — она считает свои импульсы независимо от того, что происходит в компьютере. Однако, максимальный программируемый интервал составляет приблизительно 1/12 секунды. Для подсчета интервалов времени в часы и минуты нужны какие-то другие средства. Именно по этой причине импульсы от нулевого канала микросхемы таймера накапливаются в переменной, находящейся в области данных BIOS. Это накопление обычно называется подсчетом времени суток. 18. 2 раза в секунду выход канала 0 обрабатывается аппаратным прерыванием (прерыванием таймера), которое ненадолго останавливает процессор и увеличивает счетчик времени суток. [10]

Число 0 соответствует полночи 12: 00; когда счетчик достигает значения эквивалентного 24 часам, он сбрасывается на ноль. Другое время в течение суток легко определяется делением показателя счетчика на 18. 2 для каждой секунды. Счетчик времени суток используется в большинстве операций, связанных со временем.

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

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

Касвандс Э. Г. Введение в программирование на языке Ассемблер. ч. 1 — М. : ЮНИТИ — ДАНА, 2006.

Юров В. Assembler. Специальный справочник. — СПб. : Питер, 2007.

Что такое ассемблер. [Электронный ресурс]. — Режим доступа: http://www.assembler.webservis.ru

Ваулин А. С. Языки программирования. кн. 5 — М. : Школа-Пресс, 2008.

Малютин Э. А. Языки программирования. — М. : Просвещение, 2008.

Абель П. Язык Ассемблера для IBM PC и программирования /Пер. с англ. Ю. В. Сальникова — М. ; Высшая школа 2007 — 447 с. : ил.

Программируем на ассемблере. [Электронный ресурс]. — Режим доступа: http://www.kalashnikoff.ru

Зубков С. В. Assembler для DOS, Windows и Unix. — М. : ИНФРА-М, 2009.

Богумирский Б. Эффективная работа на IBM PC в среде Windows 95 СПб, «Питер», 2007.

Юров В., Хорошенко В. Assembler — Учебный курс. — СПб. : Питер, 2007.

; mov AX, data; инициализация

mov DS, AX; сегментного регистра DS

; Прочитаем и сохраним исходное содержимое вектора 8

mov word ptr old_08h, BX

mov word ptr old_08h+2, ES

; Установим наш обработчик прерываний new_08h

mov DX, offset new_08h

push DS; Сохраним на время DS

push CS; Отправим содержимое CS

int 21h; Вызов DOS (функции 25h)

pop DS; Восстановим DS

; Сымитируем действия, выполняемые в течение 3 с, просто зациклив программу

; Вторая ветвь программы, активизируемая по истечении 3 с

Основы Ассемблера

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

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

Комментарии в ваших программах оставляются после точки с запятой. Точно также как в дельфи или си через //.

Числа в ассемблере могут представляться в двоичной, десятеричной или шестнадцатеричной системе. Для того, чтобы показать в какой системе использовано число надо поставить после числа букву. Для бинарной системы пишется буква b (пример: 0000010b, 001011010b), для десятеричной системы можно ничего не указывать после числа или указать букву d (примеры: 4589, 2356d), для шестнадцатеричной системы надо указывать букву h, шестнадцатеричное число надо обязательно писать с нулём в начале (примеры: 00889h, 0AC45h, 056Fh, неправильно F145Ch, С123h).

Самая первая команда будет хорошо всем известная MOV. Эта команда используется для копирования (не обращайте внимания на имя команды) значения из одного места в другое. Это ‘место’ может быть регистр, ячейка памяти или непосредственное значение (только как исходное значение). Синтаксис команды:

Вы можете копировать значение из одного регистра в другой.

Вышеприведенная команда копирует содержание ecx в edx. Размер источника и приемника должны быть одинаковыми,

например: эта команда — НЕ допустима:

Этот опкод пытается поместить DWORD (32-битное) значение в байт (8 битов). Это не может быть сделано mov командой (для этого есть другие команды).

А эти команды правильные, потому что у них источник и приемник не отличаются по размеру:

Вы также можете получить значение из памяти и поместить эго в регистр. Для примера возьмем следующую схему памяти:

смещение 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42
данные 0D 0A 50 32 44 57 25 7A 5E 72 EF 7D FF AD C7

(Каждый блок представляет байт)

Значение смещения обозначено здесь как байт, но на самом деле это это — 32-разрядное значение. Возьмем для примера 3A, это также — 32-разрядное значение: 0000003Ah. Только, чтобы с экономить пространство, некоторые используют маленькие смещения.

Посмотрите на смещение 3A в таблице выше. Данные на этом смещении — 25, 7A, 5E, 72, EF, и т.д. Чтобы поместить значение со смещения 3A, например, в регистр, вы также используете команду mov:

Означает: поместить значение с размером DWORD (32-бита) из памяти со смещением 3Ah в регистр eax. После выполнения этой команды, eax будет содержать значение 725E7A25h. Возможно вы заметили, что это — инверсия того что находится в памяти: 25 7A 5E 72. Это потому, что значения сохраняются в памяти, используя формат little endian . Это означает, что самый младший байт сохраняется в наиболее значимом байте: порядок байтов задом на перед. Я думаю, что эти примеры покажут это:

  • dword (32-бит) значение 10203040 шестнадцатиричное сохраняется в памяти как: 40, 30, 20, 10
  • word (16-бит) значение 4050 шестнадцатиричное сохраняется в памяти как: 50, 40

Вернемся к примеру выше. Вы также можете это делать и с другими размерами:

Вы, наверное, уже поняли, что префикс ptr обозначает, что надо брать из памяти некоторый размер. А префикс перед ptr обозначает размер данных:

Иногда размер можно не указывать:

Так как eax — 32-разрядный регистр, ассемблер понимает, что ему также требуется 32-разрядное значение, в данном случае из памяти со смещением 403045h.

Можно также непосредственные значения:

Эта команда просто запишет в регистр edx, значение 5006. Скобки, [ и ], используются, для получения значения из памяти (в скобках находится смещение), без скобок, это просто непосредственное значение.

Можно также использовать регистр как ячейку памяти (он должен быть 32-разрядным в 32-разрядных программах):

В mov cx, [eax], процессор сначала смотрит, какое значение (= ячейке памяти) содержит eax, затем какое значение находится в той ячейке памяти, и помещает это значение (word, 16 бит, потому что приемник, cx, является 16-разрядным регистром) в CX.

Стековые операции — PUSH, POP. Перед тем, как рассказать вам о стековых операциях, я уже объяснял вам, что такое стек. Стек это область в памяти, на которую указывает регистр стека ESP. Стек это место для хранения адресов возврата и временных значений. Есть две команды, для размещения значения в стеке и извлечения его из стека: PUSH и POP. Команда PUSH размещает значение в стеке, т.е. помещает значение в ячейку памяти, на которую указывает регистр ESP, после этого значение регистра ESP увеличивается на 4. Команда Pop извлекает значение из стека, т.е. извлекает значение из ячейки памяти, на которую указывает регистр ESP, после этого уменьшает значение регистра ESP на 4. Значение, помещенное в стек последним, извлекается первым. При помещении значения в стек, указатель стека уменьшается, а при извлечении — увеличивается. Рассмотрим пример:

  • 1: поместить 100 в ecx
  • 2: поместить 200 в eax
  • 3: разместить значение из ecx (=100) в стеке (размещается первым)
  • 4: разместить значение из eax (=200) в стеке (размещается последним)
  • 5/6/7: выполнение операций над ecx, значение в ecx изменяется
  • 8: извлечение значения из стека в ebx: ebx станет 200 (последнее размещение, первое извлечение)
  • 9: извлечение значения из стека в ecx: ecx снова станет 100 (первое размещение, последнее извлечение)

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

(стек здесь заполнен нулями, но в действительности это не так, как здесь). ESP стоит в том месте, на которое он указывает)

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

Когда выполняется команда call, процессор передает управление на код с адреса 455659, и выполняет его до команды ret, а затем возвращает управление команде следующей за call. Код который вызывается командой call называется процедурой. Вы можете поместить код, который вы часто используете в процедуру и каждый раз когда он вам нужен вызывать его командой call.

Подробнее: команда call помещает регистр EIP (указатель на следующюю команду, которая должна быть выполнена) в стек, а команда ret извлекает его и передаёт управление этому адресу. Вы также можете определить аргументы, для вызываемой программы (процедуры). Это можно сделать через стек:

Внутри процедуры, аргументы могут быть прочитаны из стека и использованы. Локальные переменные, т.е. данные, которые необходимы только внутри процедуры, также могут быть сохранены в стеке. Я не буду подробно рассказывать об этом, потому, что это может быть легко сделано в ассемблерах MASM и TASM. Просто запомните, что вы можете делать процедуры и что они могут использовать параметры.

Одно важное замечание: регистр eax почти всегда используется для хранения результата процедуры.

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

Вот и кончился очередной урок. На следующем уроке мы напишем первую программу на ассемблере.

Assebler — assembler-актуальность его использования

Язык Ассемблер (Assembler) — это низкоуровневый язык программирования. Он хоть и сложный, но написанные на нем программы работают быстрее, чем на Паскале и на Си. Хотя Си старается оптимизировать скорость выполнения программ, но она никогда не обгонит ассемблер. Достоинства языка состоят в том, что программист может написать более высокоскоростную программу, чем на других языках высокого уровня. Также Ассемблер используется для написания прошивок на BIOS, а также возможет непосредственный доступ к регистрам процессора, и к портам компьютера. В данном обучающем курсе приведены написания программ, или другими словами ассемблер на примерах, а также ассемблер под windows.

Написанная информация была с использованием книги: Рисований О.М. Системне програмування: Підручник. – Х.: НТУ “ХПІ”, 2010. – 912 с.

Материалы по программированию ищите на сайте allrefs.net.

Введение в язык Ассемблер

Дата добавления: 2009-12-10

Для того, чтобы программировать на Assembler, необходимо:

Программа MASM_v9.0 или MASM_v10.0
Отладчик, например: OLLYDBG.EXE
В установленном месте, где находится программа MASM, создаете файл: aaa.bat

Я выбрал такое название (aaa.bat) для того, чтобы она была в самом верху. И вы могли всегда его видеть. В этом aaa.bat вносите такую информацию:

Арифметические операции Ассемблер. Команды Ассемблера

Дата добавления: 2010-01-10

Программирование арифметических выражений в языке Ассемблер происходит через некоторые команды такие, как: mul, div, sub, add. Эти команды называются командами арифметических операций.

Двумерные массивы на Ассемблере. Ассемблер двумерными массивами примеры


Дата добавления: 2010-01-15

В данном уроке паказывается ввод элементов в двумерный массив. Приводится пример нахождение максимального элемента массива в ассемблере. И происходит вывод в MessageBox.

Ассемблер структуры. Примеры задач

Дата добавления: 2010-01-17

Пример: Задана матрица 3 X 4. Определить максимальный элемент каждой строки. Результат выполнения программы вывести в окно консоли.

Ассемблер работа с файлами. Запись в файл

Дата добавления: 2010-01-18

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

API-подобные процедуры в языке Ассемблер. Процедуры в Assembler

Дата добавления: 2010-01-20

Процедуры в языке Ассемблер работают также, как и в других языках программирования.

1 | 2 | 3 | Следующая | Последняя

Assembler (Ассемблер) — машинно-ориентированный язык программирования низкого уровня, в котором имеются команды. Эти команды соответствуют машинным кодам. Этот язык был разработан в 1950-х годах. Команды ассемблера полностью соответствуют командам процессора. Они являются более удобной для человека символьной формой записи— мнемокоды — команд и их аргументов. На языке ассемблера пишутся драйвера, компьютерные игры , а ранее игры для игровых приставок, программы для микроконтроллеров и процессоров, вирусы и, соответственно, антивирусы. Его применяют для создания трансляторов языков программирования, с его помощью можно соединять фрагменты кода разных программ. Помимо этого на ассемблере были написаны такие операционные системы, как первая версия UNIX и MenuetOS.

Компиляторы для Assembler:

Turbo Assembler 5.0

Lazy Assembler (LZASM)

Учебники по Assembler:

Название: Язык Ассемблера, уроки программирования.
Автор: П.И. Рудаков, К.Г. Финогенов
Скачать:

Название: Проектирование и дизайн пользовательского интерфейса
Автор: А.К.Гультяев, В.А.Машин
Скачать:

Название: Программируемые логические контроллеры.
Практическое руководство для начинающего инженера
Автор: И. Г. Минаев, В.

Погружение в assembler. Полный курс по программированию на асме от ][

В. Самойленко .
Скачать:

Название: Микроконтроллеры серии 8051. Практический подход
Автор: Ю. С. Магда
Скачать:

Название: Практическое программирование микроконтроллеров Atmel AV R на языке ассемблера
Автор:Ю. В.Ревич
Скачать:

Programm.ws — это сайт, на котором вы можете почитать литературу по языкам программирования, а так-же посмотреть примеры работающих программ на С++, ассемблере, паскале и много другого..

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

4 лучших книги по ассемблеру: знания и навыки шаг за шагом

Соответственно, люди, которые этим занимаются, называются программистами (на профессиональном жаргоне — кодерами), а те, кто разрабатывает алгоритмы — алгоритмистами, специалистами предметной области, математиками.
В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения ЭВМ. Более точен современный термин — «программная инженерия» (также иначе «инженерия ПО»). Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение.

Язык ассемблера — тип языка программирования низкого уровня, см. подробнее о происхождении и использовании термина.

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

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

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

Связывание ассемблерного кода с другими языками

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

Комбинирование достигается несколькими приемами:

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

Единого стандарта для синтаксиса языков ассемблера не существует, конкретный разработчик волен установить свои собственные синтаксические правила. Однако существуют традиционные подходы, которых придерживаются языки ассемблера для наиболее распространённых процессорных архитектур, своего рода стандарт de facto. Так основными стандартами являются стандарты — Intel и AT&T.

Каждая инструкция записывается в отдельной строке.

Полный формат каждой строки инструкций следующий:

label: code ; comment

где label — название метки; code — собственно, инструкция языка ассемблера; comment — комментарий.

При этом один или два компонента строки могут отсутствовать, то есть строка может состоять, к примеру, только из комментария, или содержать только метку или инструкцию.

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

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

jmp — продолжать выполнение с нового адреса памяти (от англ. jump — прыжок)
mov — переместить данные (от англ.

404 Not Found

move — передвинуть)
sub — получить разность двух значений (от англ. subtract — вычесть)
xchg — обменять значения в регистрах/ячейках памяти (от англ. exchange — обмен)

От ассемблера к ассемблеру меняется синтаксис аргументов, но мнемоники, обычно, остаются одинаковыми (такими какие используются в оригинальной спецификации процессора), за исключением двух случаев: Если ассемблер использует кроссплатформенный AT&T-синтаксис, то оригинальные мнемоники приводятся к синтаксису AT&T.

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

Например процессор Zilog Z80 наследовал систему команд Intel i8080, расширил ее и поменял мнемоники (и обозначения регистров) на свой лад. Например сменил интеловские «mov» на «ld» (команда перемещения данных). Процессоры Motorola Fireball наследовали систему команд Z80, несколько её урезав. Вместе с тем, Motorola официально вернулась к мнемоникам Intel. И в данный момент половина ассемблеров для Fireball работает с интеловскими мнемониками, а половина с мнемониками Zilog.

Текст программ может быть дополнен директивами ассемблера (параметры, влияющие на процесс ассемблирования и свойства выходного файла).

Каждый ассемблер имеет собственные директивы.

Для упрощения и ускорения написания программ на языке ассемблера служат макросы.

Достоинства языка ассемблера

Максимально оптимальное использование средств процессора, использование меньшего количества команд и обращений в память, и как следствие — большая скорость и меньший размер программы
Использование расширенных наборов инструкций процессора (MMX, SSE, SSE2, SSE3)
Доступ к портам ввода-вывода и особым регистрам процессора (в большинстве ОС эта возможность доступна только на уровне модулей ядра и драйверов)
Возможность использования самомодифицирующегося (в том числе перемещаемого) кода (под многими платформами эта возможность недоступна, так как запись в страницы кода запрещена, в том числе и аппаратно, однако в большинстве общедоступных систем из-за их врожденных недостатков имеется возможность исполнения кода содержащегося в сегменте (секции) данных, куда запись разрешена)
Максимальная «подгонка» для нужной платформы

NB: Последние технологии безопасности, внедряемые в операционные системы и компиляторы, не позволяют делать самомодифицирующего кода, так как исключают одновременную возможность исполнения программы и запись в одном и том же участке памяти (технология W^X).

Технология W^X используется в OpenBSD (где и появилась), в других BSD-системах, в Linux; в Microsoft Windows (начиная с Windows XP SP2) используется схожая технология DEP.

Большие объемы кода, большое число дополнительных мелких задач, меньшее количество доступных для использования библиотек, по сравнению с языками высокого уровня
Трудоёмкость чтения и поиска ошибок (хотя здесь многое зависит от комментариев и стиля программирования)
Зачастую компилятор языка высокого уровня, благодаря современным алгоритмам оптимизации, даёт более эффективную программу (по соотношению качество/время разработки).
Непереносимость на другие платформы (кроме совместимых).
Ассемблер более сложен для совместных проектов.

Пример программы на языке ассемблера

Пример программы для операционной системы DOS на процессоре семейства Intel x86, выдающей на экран приветствие (написан на TASM):

mov bx,1 ; указание направления вывода (на экран)
mov cx,13 ; указание количества символов строки
mov dx,offset msg ; поместить в регистр DX смещение строки
mov ah,40h ; выбор функции вывода строки
int 21h ; вызов прерывания DOS «Набор процедур» для вывода строки
int 20h ; вызов прерывания DOS (завершение программы)

msg DB ‘Hello, World!$’

msg — метка (идентификатор), упрощающая доступ к данным.
Происхождение и критика термина «язык ассемблера»

Данный тип языков получил свое название от названия транслятора (компилятора) с этих языков — ассемблера (англ. assembler — сборщик). Название последнего обусловлено тем, что на древних компьютерах не существовало языков более высокого уровня, и единственной альтернативой созданию программ с помощью ассемблера было программирование непосредственно в кодах.

Язык ассемблера в русском языке часто называют «ассемблером» (а что-то связанное с ним — «ассемблерный»), что, согласно английскому переводу слова, неправильно, но вписывается в правила русского языка. Однако, сам ассемблер (программу) тоже называют просто «ассемблером», а не «компилятором языка ассемблера» и т.п.

Использование термина «язык ассемблера» также может вызвать ошибочное мнение о существовании единого языка низкого уровня, или хотя бы стандарта на такие языки. При именовании языка, на котором написана конкретная программа, желательно уточнять, для какой архитектуры она предназначена и на каком диалекте языка написана.

Assebler — assembler-актуальность его использования

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

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

Как известно, универсального языка программирования пока не придумали и потребность в нем совсем не очевидна. Поэтому, для расширения сферы деятельности и повышения профессионального уровня, программист должен владеть несколькими языками (быть полиглотом) и желательно, чтобы одним из них был ассемблер. Ниже я попытаюсь обосновать эту точку зрения.

Ассемблер (assembly language, assembler) является машинно-ориентированным языком программирования. В переводе с английского слово assembly означает собрание, сборка, монтаж и т. п. Выбор такого названия объясняется тем, что первые трансляторы с Алгола, Фортрана, Кобола и PL/I использовали ассемблер в качестве промежуточного языка при сборке программы из отдельных модулей.

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

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

С появлением персональных компьютеров (ПК) маятник качнулся в обратную сторону и, на некоторое время, ассемблер вновь оказался в числе лидеров. Это произошло потому, что ограниченные возможности первых моделей ПК не позволяли применять компиляторы с языков высокого уровня. Но технический прогресс постепенно все расставил по своим местам, и программисты вновь стали отдавать предпочтение алгоритмическим языкам.

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

Специфические особенности языка

Ассемблер является языком программирования низкого уровня, составленная на нем программа представляет собой последовательность команд конкретной ЭВМ, чаще конкретного семейства ЭВМ, записанных в некой условной мнемонической форме. Именно машинная ориентация определяет достоинства и недостатки этого языка.

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

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

Очевидным недостатком является низкий уровень абстрагирования от особенностей конкретной ЭВМ, необходимость знать и учитывать эти особенности. В то время как при работе с языками высокого уровня программист может полностью сосредоточить свое внимание на особенностях реализуемого алгоритма.

Другим недостатком является большое, а иногда и очень большое, количество команд, выполняемых конкретной машиной. Например, у микропроцессора Pentium 4 их около 500! Это вынуждает пользоваться при работе специальными справочниками, — не держать же в голове все разнообразие имен команд и особенностей их выполнения.

Ассемблер и макроассемблер

С точки зрения программиста язык ассемблера является подмножеством языка макроассемблера. Последний обязательно компилирует полный набор инструкций конкретного семейства микропроцессоров и, кроме того, исполняет большой набор операторов и директив (далее макросредств) различного назначения. У программистов, работающих на компьютерах IBM PC, наибольшей популярностью пользуются макроассемблеры MASM (компании Microsoft) и TASM (компании Borland), имеющие примерно одинаковые возможности и во многом (но не полностью) совместимые. В данном разделе мы будем говорить об особенностях MASM.

Прежде всего, следует отметить, что в чистом виде язык ассемблера применяется только при оформлении вставок в тексты программ, составляемых на языках высокого уровня. Без использования макросредств невозможно составить даже простую подпрограмму, не говоря о завершенных программах, а вот без использования команд ассемблера это возможно.

При определенных условиях исходный текст программы, выполняющей достаточно сложные действия, может содержать только макросредства. В нем не будет ни одной команды ассемблера! О какой сложности и трудоемкости программирования можно говорить в подобных случаях?

В руководствах по MASM, в том числе и в HELP, обычно описываются 8 типов операторов и 12 типов директив, начиная с версии MASM 6.10, их количество не изменялось. В рамках данной статьи не имеет смысла приводить полное описание макросредств, поэтому мы ограничимся их общей характеристикой.

Директивы макроассемблера предназначены для выполнения трех основных категорий действий:

  1. управление распределением оперативной памяти выполняют директивы, предназначенные для описания простых переменных, структур данных, записей и сегментирования программ;
  2. управление работой с внешними и внутренними подпрограммами, фрагментами программ и макроопределениями выполняют директивы их явного или предварительного описания и вызова;
  3. управление процессом компиляции программы выполняют директивы условной компиляции, среди них встречаются такие знакомые каждому программисту имена, как IF, ELSE, FOR, WHILE, REPEAT, GOTO.

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

Таким образом, при обсуждении достоинств и недостатков программирования на ассемблере не следует забывать, что на практике мы, как правило, работаем с языком макроассемблера, а это далеко не одно и тоже.

Ахиллесовой пятой ассемблера является трудоемкость программирования на этом языке. Что может сделать программист для упрощения собственного труда?

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

  1. В состав полной версии системы программирования на макроассемблере (дистрибутивного пакета) входит набор макроопределений и подпрограмм различного назначения и примеры их использования. Внимательно просмотрите все подкаталоги вашей версии макроассемблера, наверняка в них найдутся полезные и интересные решения, которые можно применять в вашей работе.
  2. Не забывайте о том, что при составлении программ можно использовать модули библиотек, входящих в состав систем программирования на языках высокого уровня, например, на Си. Правда, для этого надо иметь описание этих библиотек, но без него невозможно их использование и в рамках той системы программирования, для которой они созданы.
  3. Если у вас есть доступ к сети Internet, то на разных ее сайтах можно найти множество готовых решений буквально на все случаи жизни. Только обращайте внимание на даты разработки программ и подпрограмм. Многие из них морально устарели и при использовании новых инструкций микропроцессоров могут быть существенно упрощены.
  4. В процессе работы с ассемблером у вас постепенно будет накапливаться набор собственных решений, которые пригодятся в новых разработках. Для удобства их последующего использования старайтесь при написании программ составлять как можно больше подпрограмм, оформленных в виде отдельных модулей, лучше исходных, а не объектных — первые проще модифицировать в случае необходимости. Применение подпрограмм несколько увеличивает размеры задачи и замедляет процесс ее выполнения. Но взамен вы получаете возможность отлаживать большую программу по частям и использовать отлаженные подпрограммы в других своих разработках.
  5. Не забывайте о существовании такого эффективного средства, как макросы — макроопределения и макровызовы. Они позволяют сокращать не только исходный текст программы, но и количество возможных ошибок при его наборе. Кроме того, макровызовы удобно применять при запросе системных функций, которые выполняют много полезных действий таких, как работа с окнами, с файловой системой, ввод и вывод данных и пр.

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

Когда ассемблеру нет альтернативы

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

Обвинять в этом разработчиков компиляторов не имеет смысла, — проблема не столь тривиальна, и для ее решения нужно не только улучшать технику компиляции, но и разрабатывать принципиально новые языковые средства. Мы привыкли к тому, что арифметические и логические операции выполняются над одной парой операндов, иногда над одним операндом (смена знака или отрицание). А групповые операции современных микропроцессоров (не только семейства Pentium) могут оперировать сразу с несколькими парами операндов, количество и разрядность которых не фиксированы.

В этой ситуации альтернативы ассемблеру просто не существует. Недаром в технической документации к компилятору «Intel C++ Compiler» рекомендуются три варианта работы с новыми командами:

  1. прямые вставки ассемблерного текста в тело программы, написанной на Си;
  2. составление процедур (подпрограмм) на языке ассемблера;
  3. использование Intrinsic (встроенные функции).

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

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

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

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

Компания Intel разработала и продает специальный анализатор производительности микропроцессора в процессе выполнения конкретной задачи (VTuneTM Performance Analyzer 6.0). Он позволяет выявить в ней слабые места (критические участки кода задачи), и затем исправить их с помощью ассемблерных вставок.

Подробнее о новых возможностях микропроцессоров вы можете прочитать в моей статье «Pentium глазами программиста»[1]. В Internet она опубликована на странице http://www.macro.aaanet.ru/apnd_4.html

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

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

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

Цукерберг рекомендует:  SEO в Magento Оптимизация страниц и избегание штрафов за дублирующееся содержимое
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих