|
Ушел с форума
16371 / 7683 / 1080
Регистрация: 11.11.2010
Сообщений: 13,757
|
|||
| 10.11.2013, 16:55 [ТС] | |||
|
ПРЕДИСЛОВИЕ Ассемблер (Assembler) — язык программирования, понятия которого отражают архитектуру электронно-вычислительной машины. Язык ассемблера — символьная форма записи машинного кода, использование которого упрощает написание машинных программ. Для одной и той же ЭВМ могут быть разработаны разные языки ассемблера. В отличие от языков высокого уровня абстракции, в котором многие проблемы реализации алгоритмов скрыты от разработчиков, язык ассемблера тесно связан с системой команд микропроцессора. Для идеального микропроцессора, у которого система команд точно соответствует языку программирования, ассемблер вырабатывает по одному машинному коду на каждый оператор языка. На практике для реальных микропроцессоров может потребоваться несколько машинных команд для реализации одного оператора языка. Язык ассемблера обеспечивает доступ к регистрам, указание методов адресации и описание операций в терминах команд процессора. Язык ассемблера может содержать средства более высокого уровня абстракции: встроенные и определяемые макрокоманды, соответствующие нескольким машинным командам, автоматический выбор команды в зависимости от типов операндов, средства описания структур данных. Главное достоинство языка ассемблера — «приближенность» к процессору, который является основой используемого программистом компьютера, а главным неудобством — слишком мелкое деление типовых операций, которое большинством пользователей воспринимается с трудом. Однако язык ассемблера в значительно большей степени отражает само функционирование компьютера, чем все остальные языки. И хотя драйвера и операционные системы сейчас пишут на Си, но Си при всех его достоинствах — язык высокого уровня абстракции, скрывающий от программиста различные тонкости и нюансы железа, а ассемблер — язык низкого уровня абстракции, прямо отражающий все эти тонкости и нюансы. Для успешного использования ассемблера необходимы сразу три вещи:
Оптимальной можно считать программу, которая работает правильно, по возможности быстро и занимает, возможно, малый объем памяти. Кроме того, ее легко читать и понимать; ее легко изменить; ее создание требует мало времени и незначительных расходов. В идеале язык ассемблера должен обладать совокупностью характеристик, которые бы позволяли получать программы, удовлетворяющие как можно большему числу перечисленных качеств. На языке ассемблера пишут программы или их фрагменты в тех случаях, когда критически важны:
Языки программирования высокого уровня абстракции разрабатывались с целью возможно большего приближения способа записи программ к привычным для пользователей компьютеров тех или иных форм записи, в частности математических выражений, а также чтобы не учитывать в программах специфические технические особенности отдельных компьютеров. Язык ассемблера разрабатывается с учетом специфики процессора, поэтому для грамотного написания программы на языке ассемблера требуется, в общем, знать архитектуру процессора используемого компьютера. Однако, имея в виду преимущественное распространение PC-совместимых персональных компьютеров и готовые пакеты программного обеспечения для них, об этом можно не задумываться, поскольку подобные заботы берут на себя фирмы-разработчики специализированного и универсального программного обеспечения. Ответы на контрольные вопросы необязательно находятся в той главе, под которой они помещены. Иногда придется просмотреть и все пособие. Автор придерживается мнения, что программирование на языке ассемблера — это искусство, которое основано на нескольких основных законах и включает в себя большое количество практических приемов и правил. Математических выкладок вы встретите очень мало, зато приводятся разнообразные примеры программ и всячески пропагандируется быстрая прикидочная оценка параметров и характеристик, которую желательно производить «в уме». Вы не будете читать введение, не понимая языка, на котором оно написано. Это замечание относится к любой книге (исключая книжки-картинки). Чтобы получить от пособия максимум полезного, у Вас должны быть определенные знания, и Вы уже должны уметь делать нечто большее, чем просто читать. Данное пособие отнюдь не предназначено служить введением в программирование для ЭВМ. Предполагается, что читатель имеет некоторый опыт в этой области. Читатель должен:
Введение в язык ассемблера Язык программирования — это система обозначений для описания данных и алгоритмов их обработки на компьютере. Программы для первых вычислительных машин составлялись на простейшем из языков программирования — машинном коде, при помощи только двух символов: нуля и единицы. Первое время программы писали в двоичном коде, но вскоре, программисты придумали себе облегчение — программы стали писать не в двоичной, а в шестнадцатеричной системе счисления. Для перевода из двоичной в шестнадцатеричную систему счисления каждые четыре двоичные цифры заменяют одной шестнадцатеричной цифрой (глава «Представление данных»). Например, (1010 0010 0000 0111)2 = (A207)16. Программа на машинном коде имеет вид таблицы из цифр, каждая ее строчка соответствует одному оператору — машинной команде, которая является приказом компьютеру выполнить определенные действия. Конструкциями машинного кода являются константы и команды. Команда разделяется на группы бит (или поля). Первые несколько бит это поле — код операции (также операционный код, опкод — англ operation code), которое показывает, что должен делать компьютер (складывать, умножать и тому подобное). Остальные поля, называемые операндами, идентифицируют требуемую команде информацию, показывают, где именно в памяти компьютера находятся нужные числа (слагаемые, сомножители и тому подобное) и куда следует поместить результат операции (сумму, произведение и так далее). Операнд может содержать данные, часть адреса, косвенный указатель на данные или другую информацию, относящуюся к обрабатываемым командой данным. Например, команда перемещения для микропроцессора Intel x86 выглядит так: C605EF00400005. C605 — опкод операции перемещения. По такой команде компьютер помещает число 05 (две последние цифры 05) в ячейку памяти с номером 004000EF (цифры EF004000). Концепция Джона фон Неймана Джон фон Нейман (John von Neumann) — профессор математики в Принстонском Институте сложных исследований — помогал проектировать компьютер EDVAC (Electronic Discrete Variable Automatic Computer — Электронный автоматический компьютер с дискретными переменными). В статье «Предварительное обсуждение логической конструкции электронной вычислительной машины», опубликованной в 1946 в соавторстве с Артуром Берксом (Arthur Burks) и Германом Гольдстайном (Herman Goldstine), он описал некоторые особенности компьютеров. Впоследствии оказалось, что концепция Джона фон Неймана настолько мощна и универсальна, что используется и по сей день в современных компьютерах:
Центральный процессор (АЛУ с блоком управления) реализуется микропроцессором семейства х86 — от 8086/88 до Pentium 4. При всей своей внутренней суперскалярности, суперконвейеризированности и спекулятивности, внешне процессор соблюдает вышеупомянутый принцип последовательной передачи управления. Набор арифметических, логических и прочих инструкций насчитывает несколько сотен, а для потоковой обработки придуман принцип SIMD — множество комплектов данных, обрабатываемых одной инструкцией (расширения ММХ, 3DNow!, SSE). Процессор имеет набор регистров, часть которых доступна для хранения операндов, выполнения действий над ними и формирования адреса инструкций и операндов в памяти. Другая часть регистров используется процессором для служебных (системных) целей, доступ к ним может быть ограничен (есть даже программно-невидимые регистры). Память распределена по нескольким компонентам:
Устройства ввода/вывода (УВВ) служат для преобразования информации из внутреннего представления в компьютере (биты и байты) в форму, доступную окружающим, и обратно. К устройствам ввода относятся клавиатура, мышь, джойстик, микрофон, сканер, видеокамера, различные датчики; к устройствам вывода — дисплей, принтер, плоттер, акустические системы, исполнительные механизмы. Устройства хранения вместе с УВВ можно объединить общим понятием периферийные устройства. Существует также класс коммуникационных устройств, предназначенных для передачи информации между компьютерами и (или) их частями. Эти устройства обеспечивают, например, соединение компьютеров в локальные сети или подключение терминала (это УВВ) к компьютеру. Периферийные и коммуникационные устройства (и даже память) снабжаются контроллерами или адаптерами, которые доступны процессору. Все компоненты компьютера представляются для процессора в виде наборов ячеек памяти или (и) портов ввода/вывода. Процессор может адресоваться к ним с точностью до одного байта — набора смежных восьми бит. Каждый байт (ячейка памяти, порт) имеет собственный уникальный физический адрес. Этот адрес устанавливается на системной шине процессором, когда он инициирует обращение к данной ячейке или порту. В семействе х8б и PC-совместимых компьютерах пространства адресов / ячеек памяти и портов ввода/вывода разделены. Это предусмотрено с обеих сторон: процессоры позволяют, а компьютеры используют данное разделение. В принципе, это разделение не обязательно, существуют процессоры, для которых все внешние ячейки рассматриваются только как память. Контроллеры и адаптеры периферийных устройств могут и не использовать порты в пространстве ввода/вывода, если их регистры отображены на пространство памяти. За историю PC типовой объем ОЗУ вырос уже на три порядка и подбирается к гигабайту. Микропроцессор Intel 8086 имел разрядность шины адреса 20 бит, что позволяло адресовать 220=1.048.576 ячеек (1 Мбайт). Сейчас микропроцессоры имеют разрядность физического адреса памяти 32/36 бит, что позволяет адресовать до 4 Гбайт/64 Гбайт соответственно. Пространство ввода/вывода использует только младшие 16 бит адреса, что позволяет адресовать до 216=65.536 однобайтных регистров. Адреса системных устройств копьютеров на базе Intel x86 не меняются. Пространства памяти и ввода/вывода неравнозначны не только по объему, но и по способам обращения. Способов адресации к ячейке памяти в х86 великое множество, в то время как для адресации ввода/вывода их существует только два. При обращении к памяти используется виртуальная адресация, при которой для программиста, программы и пользователя создается иллюзия оперативной памяти гигантского размера. Реальный физический адрес процессор формирует из логического адреса (указанного программистом) под управлением операционной системы, поддерживающей виртуальную память. Иллюзия большого объема создается операционной системой с помощью устройств хранения и специальных аппаратных средств процессора. Возможна реальная адресация к памяти — в этом случае физический адрес совпадает с логическим. К портам ввода/вывода обращаются только по реальным адресам, правда, и здесь возможна виртуализация чисто программными средствами операционной системы. Самое существенное различие пространств памяти и ввода/вывода — процессор может считывать инструкции для исполнения только из пространства памяти. Хотя через порт ввода можно считать фрагмент программного кода (например, при считывании данных с диска), но для того чтобы этот код исполнить, его необходимо записать в память. Процессор исполняет программный код, находящийся к моменту исполнения в пространстве памяти. Программный код — это последовательность команд, или инструкций, каждая из которых определенным образом закодирована и расположена в целом числе смежных байт памяти. Каждая инструкция обязательно имеет операционную часть, несущую процессору информацию о требуемых действиях. Операндная часть, указывающая процессору, где находятся операнды, может присутствовать в явном или неявном виде или отсутствовать. Операндная часть может описывать от нуля до двух операндов, участвующих в данной инструкции (есть инструкции, в которые кроме двух операндов задается еще и параметр инструкции). Здесь могут быть
Последовательность исполнения инструкций, предписанная программным кодом, может быть нарушена под воздействием внутренних или внешних (относительно процессора) причин. К внутренним причинам относятся исключения (exceptions) — особые ситуации, возникающие при выполнении инструкций. Наглядным примером исключения является попытка деления на ноль. При возникновении условия исключения процессор автоматически выполняет вызов процедуры обработки исключения, после которой он может вернуться к повторному исполнению инструкции, породившей исключение или следующей за ней. Вариант поведения зависит от типа произошедшего исключения. Исключения широко используются современными операционными системами, на основе обработки исключений строится система виртуальной памяти и реализуются многие функции многозадачных операционных систем. Внешними причинами изменения нормальной последовательности инструкций являются аппаратные прерывания — вызовы процедур под воздействием электрических сигналов, поступающих на специальные выводы процессора. Эти сигналы могут подаваться неожиданно для исполняемой программы, но у программиста есть возможность заставить процессор игнорировать все прерывания или их часть. Злоупотреблять этой возможностью нельзя, поскольку на аппаратных прерываниях строится, синхронизация обращения к памяти и УВУ, а также другие системные и прикладные функции компьютера. Источниками аппаратных прерываний являются контроллеры и адаптеры периферийных устройств, генераторы меток времени, системы управления питанием и т.д. Есть еще так называемые программные прерывания, но они отнюдь не нарушают последовательность инструкций, предписанную программистом. Поэтому прерываниями они по сути не являются — это всего лишь особый способ вызова процедур, широко используемый для вызова системных сервисов BIOS и операционной системы. И наконец, последовательность инструкций может изменяться по сигналу аппаратного сброса или инициализации процессора. Составление программ на машинном коде — достаточно тяжелая и кропотливая работа, требующая чрезвычайного внимания и высокой квалификации программиста. Программист должен был удержать в своей памяти, где у него находятся переменные, где код программы, взаимосвязь между отдельными частями программ, но и объем памяти машины был не очень большой. Программист должен был помнить двоичные комбинации для каждого кода операции, адреса и константы, ввести их в память компьютера в правильном порядке. В программе на машинном коде очень легко ошибиться и очень трудно отыскать ошибку. Трудно расширять или сокращать уже написанные программы. Чтобы облегчить и повысить производительность труда, были созданы специальные программы ассемблеры (англ. assemble — собирать), которые выполняли рутинную работу по переводу символических команд СЛОЖИТЬ, ВЫЧЕСТЬ, ПЕРЕМЕСТИТЬ в нули и единицы машинного кода, а также разработан язык программирования — ассемблер. Язык ассемблера позволяет составлять программы, используя для обозначения команд и символьных имен легко запоминающуюся мнемонику. Символьные имена выбираются программистом и служат для обозначения ячеек памяти и переменных. Разные типы процессоров имеют разные наборы команд. Если язык программирования ориентирован на конкретный тип процессора и учитывает его особенности, то он называется языком программирования низкого уровня абстракции. В данном случае «низкий уровень» не значит «плохой». Имеется в виду, что операторы языка близки к машинному коду и ориентированы на конкретные команды процессора. Языком низкого уровня абстракции является язык ассемблера, который представляет каждую команду машинного кода, но не в виде двоичных чисел, а с помощью условных символьных обозначений, называемых мнемониками. Для написания программ для человека был бы очень удобен его родной естественный язык (русский, английский или японский), но, к сожалению, для микропроцессора он пока непонятен. Единственный язык, который понимает микропроцессор — машинный код. Поскольку микропроцессоры имеют дело с цифровыми сигналами, команды машинного кода представляют собой двоичные коды. Микропроцессор конструируется таким образом, чтобы обеспечивалось распознавание конкретной группы кодов, которая называется системой команд. Человеку нелегко пользоваться машинным кодом, поскольку смысл кода команды не ясен без соответствующего справочника. Можно заменить код каждой машинной команды коротким именем, называемым мнемоническим кодом. Например, код 01000000b или 40h для микропроцессора Intel x86 означает «увеличить содержимое регистра EAX на единицу», выглядит как «INC EAX». Мнемонической командой служит трёх- или четырёхбуквенное сокращение английского глагола (см. табл. 1). От ассемблера к ассемблеру меняется синтаксис аргументов, но мнемоники, обычно, остаются одинаковыми. В данном случае нет нужды помнить машинные коды каждой команды, а смысл каждой команды запоминается легче, чем ее код. Машинный код определяется главным образом конструкцией кристалла микропроцессора и не подлежит изменению. Мнемоника языка ассемблера разрабатывается изготовителем микропроцессора с ориентацией на обеспечение удобства программирования и не зависит от конструкции микропроцессора. Язык ассемблера — это не какой-то один конкретный язык программирования, а целый класс языков. Каждый микропроцессор имеет свой собственный машинный код и, следовательно, собственный язык ассемблера (разрабатываемый изготовителем микропроцессора). В данной книге будет рассмотрен язык ассемблера для микропроцессоров семейства IA32/64. Язык ассемблер для микропроцессоров IA32/64 поддерживают два синтаксиса Intel и AT&T. Под Intel-синтаксис разработаны следующие ассемблеры: MASM (Macro Assembler — Microsoft Corporation), BASM, TASM (Build-in Assembler, Turbo Assembler — Borland Inc), ASM-86 (Intel Corporation), FASM (Flat Assembler — Tomasz Grysztar), LZASM (lazzy assebmler — Степан Половников), WASM (Open Watcom Assembler — фирма Watcom), HLASM, HLA (High Level Assembler — IBM), NASM (NetWide Assembler — Simon Tatham, Julian Hall, Peter Anvin), YASM (Yet Another Assembler — Peter Johnson, Michael Urman), RosAsm (ReactOS Assembler), GoAsm (Jeremy Gordon) и т.д. Синтаксис AT&T используют AS (UNIX assembler) и GAS (GNU assembler). Все вышеперечисленные ассемблеры включают стандартные мнемонические команды, в том числе команды арифметических операций для чисел с плавающей запятой для сопроцессора. Несмотря на имеющиеся различия между этими ассемблерами, их структуры и форматы команд языков в значительной мере совместимы. В данном пособии будет рассматриваться программирование на языке Macro Assembler под 32-разрядную операционную систему Windows. Любой язык программирования задается четырьмя компонентами: алфавитом, синтаксисом, словарем и семантикой. Подобно естественным языкам, язык ассемблер строится над алфавитом основных символов (в котором записывается программа) в виде иерархической системы грамматических элементов с заданными на них отношениями (подобно словам, словосочетаниям и предложениям в естественном языке, связанным синтаксическими правилами). Элементы низшего уровня, образованные цепочками основных символов, называются лексемами. Алфавит — это набор различных символов: букв, цифр, специальных знаков и т.п. Алфавит языка ассемблера состоит из букв латинского алфавита, цифр, парных ограничителей (скобок), разделителей (знаков препинания) и некоторых знаков операций. В связи с ограниченностью алфавита существуют правила кодирования основных символов комбинациями знаков, воспринимаемых входными устройствами машины. Основные классы лексем: нумералы для изображения чисел, литералы для изображения текстов, идентификаторы для обозначения различных объектов программы. Основные объекты языка ассемблер: переменные, метки (наименования различных частей программы) и процедуры (функциональные обозначения). Смысл и назначение некоторых идентификаторов фиксируется описанием языка (закрепленные слова или словарь языка ассемблер). Алфавит языка ассемблера содержит такие символы:
Примеры идентификаторов: A, A12345, ALFA, _67890, INDEX. Словарь — совокупность заранее оговоренных служебных слов: названия команд, названия директив ассемблера, названия регистров микропроцессора; в словарных словах строчные и прописные буквы не различаются. Семантика — множество правил, позволяющих уточнить синтаксически правильные конструкции языка и определить их смысловое значение. Иными словами, зная и синтаксис, и семантику языка, можно понять, какие последовательности символов алфавита (тексты) имеют смысл, а какие — бессмысленны с точки зрения данного языка. Программы, написанные на языке ассемблера, представляют собой последовательность приказов (инструкций, операторов). Эти операторы предварительно обрабатываются при помощи транслятора (программы, которая заменит каждый оператор языка ассемблера на соответствующую ему группу машинных кодов). Однозначное преобразование одной машинной инструкции в одну команду языка ассемблера называется транслитерацией. Так как наборы инструкций для каждой модели процессора отличаются, каждой конкретной компьютерной архитектуре (платформы Intel, Alpha, SPARC, Motorola и т.д.) соответствует свой язык ассемблера, и написанная на нем программа может быть использована только в этой среде. Любую программу можно написать на языке ассемблера. С помощью ассемблера создаются очень эффективные и компактные программы, так как разработчик получает доступ ко всем возможностям процессора. Однако время и усилия, затраченные на ее написание, отладку и сопровождение будут гораздо больше того времени, которое ушло бы на реализацию такой программы на языке высокого уровня абстракции. Кроме того, написание программы на языке ассемблера существенно ограничивает возможность переноса данной программы на другие вычислительные платформы. Гораздо выгоднее программировать на языке высокого уровня абстракции, для которого компилятор создает в одной программе фрагменты для наиболее распространенных платформ компьютеров. В таком случае можно основную часть программы реализовать на языке высокого уровня абстракции, а наиболее важные или критичные по быстродействию части реализовывать в виде вставок на языке ассемблера. По мнению разных авторов, на языке ассемблера целесообразно разрабатывать такие части программы или программного комплекса, как, например, процедуры ввода/вывода низкого уровня, процедуры обработки прерывания и т.п. На языке ассемблера также разрабатываются небольшие системные приложения, драйвера устройств, модули стыковки с нестандартным оборудованием, когда важнейшими требованиями становится компактность, быстродействие и возможность прямого доступа к аппаратным ресурсам. Использование языков высокого уровня абстракции, имеющих достаточно большие ограничения, в этих случаях хотя и возможно, но весьма трудоемко. В некоторых областях, например в машинной графике, на языке ассемблера пишутся библиотеки, эффективно реализующие требующие интенсивных вычислений алгоритмы обработки изображений. Первым ассемблером и одновременно первым интерпретатором стал псевдокод и набор инструкций Short Code, разработанный в 1949 г. американцами Пресом Экертом и Джоном Мошли для ЭВМ BINAC. Решение любой задачи вначале записывалось математическими уравнениями. Те, в свою очередь, по-символьно транслировались в коды: из «a=b+c» в «S0 03 S1 07 S2». На заключительном этапе коды приобретали двоичный вид, а каждая строка после ввода автоматически выполнялась. Первая практическая задача, которую решил ассемблер, — расчет таблиц артиллерийской стрельбы для американских баллистиков. Ассемблеры на мнемонических кодах («MOV», «ADD») появились только в середине 50-х. Авторы языка ассемблер более известны изобретением вычислительных машин на вакуумных трубках: ENIC (1946 г.), BINAC (1949 г.) и прямого предка современных компьютеров UNIVAC I (1951 г.).
25
|
|||
|
Новые блоги и статьи
|
||||
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|
Фото: Daniel Greenwood
kumehtar 13.11.2025
|
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга,
Ты же видел моря и метели.
Как сменялись короны и стяги,
Как эпохи стрелою летели.
- Этот мир — это крылья и горы,
Снег и пламя, любовь и тревоги,
И бескрайние. . .
|
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1
У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\
А в самом низу файла-профиля. . .
|