Язык ассемблер. Команды и основы ассемблера

Инструмент 21.06.2019
Инструмент

Assembly Language for x86 Processors, 7e is suitable for undergraduate courses in assembly language programming and introductory courses in computer systems and computer architecture. Proficiency in one other programming language, preferably Java, C, or C++, is recommended.

Written specifically for 32- and 64-bit Intel/Windows platform, this complete and fully updated study of assembly language teaches students to write and debug programs at the machine level. This text simplifies and demystifies concepts that students need to grasp before they can go on to more advanced computer architecture and operating systems courses. Students put theory into practice through writing software at the machine level, creating a memorable experience that gives them the confidence to work in any OS/machine-oriented environment.

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

В данной книге речь идет о работе процессора в двух его основных режимах: защищенном режиме и 64-битном, который также называют long mode («длинный режим»). Также помимо изложения принципов и механизмов работы процессора в защищенном и 64-битном режимах, речь пойдет о программировании на ассемблере в операционных системах семейства Windows, как в 32-битных, так и 64-битных версиях. Рассматривается не только разработка обычных приложений для операционных систем Windows, но и разработка драйверов на ассемблере. При написании книги уделялось большое внимание именно практической составляющей, т.е. изложение материала идет только по делу и только то, что необходимо знать любому системному и низко-уровневому программисту. Последний раздел книги посвящен принципам работы многопроцессорных систем, а также работе с расширенным программируемым контроллером прерываний (APIC).
На диске, прилагаемом к книге, находятся полные исходные коды примеров к книге, а также дополнительные программы и материалы.

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

Подробно и доходчиво объясняются все основные вопросы программирования на ассемблере. Рассмотрены команды процессоров Intel, 16- и 32-разрядные регистры, основы работы с сопроцессором, сегментация памяти в реальном масштабе времени, управление клавиатурой и последовательным портом, работа с дисками и многое другое. Описано, как разработать безобидный нерезидентный вирус и антивирус против этого вируса, как написать файловую оболочку (типа Norton Commander или FAR Manager) и как писать резидентные программы.
Каждая глава состоит из объяснения новой темы, описания алгоритмов программ, многочисленных примеров и ответов на часто задаваемые вопросы. Во второе издание внесены исправления и добавлены новые примеры.
Компакт-диск содержит исходные коды всех примеров, приведенных в книге, с подробными описаниями.

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

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

Описание книги Assembler. Программирование на языке ассемблера IBM PC :
Один из лучших учебников по ассемблеру. Книга имеет малый объем. Очень хорошо изложены многие важнейшие темы — сегментация, прерывания, двоичная арифметика. Подробно рассмотрены команды ЭВМ, конструкции языка и методы программирования на нем. Изложение сопровождается многочисленными примерами. Как "краткий курс" пожалуй не имеет себе равных.

Книга представляет собой учебное пособие по языку ассемблер для персональных компьютеров типа IBM PC. Подробно рассмотрены команды этих ЭВМ, конструкция языка и методы программирования на нем. Изложение сопровождается многочисленными примерами. Для студентов и преподавателей ВУЗов, для всех желающих детально изучить язык ассемблер и приемы программирования на нем.

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

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

Описание книги Ассемблер для процессоров Intel Pentium :
Издание посвящено вопросам программирования на языке ассемблера для процессоров Intel Pentium. Рассмотрен широкий круг вопросов, начиная с основ программирования на ассемблере и заканчивая применением самых современных технологий обработки данных, таких как MMS, SSE и SSE2. Материал книги раскрывает методику оптимизации программного кода для всех поколений процессоров Intel Pentium, включая Intel Pentium 4. Теоретический материал подкреплен многочисленными примерами программного кода. Для широкого круга читателей, от студентов до опытных разработчиков программного обеспечения.

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

Описание книги Изучаем Ассемблер :
Книга посвящена основам программирования на Ассемблере в системах Windows и DOS. Знание Ассемблера необходимо профессиональному программисту для понимания работы операционной системы и компилятора. Ассемблер позволяет написать программу (или ее часть) так, что она будет быстро выполняться и при этом занимать мало места. Это любимый язык хакеров; его знание позволяет менять по своему усмотрению программы, имея только исполнимый файл без исходных текстов. В основу изложения положены короткие примеры на ассемблере MASM фирмы Microsoft, вводящие читателя в круг основных идей языка, знание которых позволяет не только писать простые программы, но и самостоятельно двигаться дальше.

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

Описание книги Использование ассемблера для оптимизации программ на C++ :
Рассматривается использование языка ассемблера для оптимизации программ, написанных на языке C++. Подробно изложены вопросы применения современных технологий обработки данных ММХ и SSE, а также использования особенностей архитектур современных процессоров для оптимизации программ. Приведены практические рекомендации по оптимизации логических структур высокого уровня, использованию эффективных алгоритмов вычислений, работе со строками и массивами данных.

В книгу включены примеры программного кода приложений, иллюстрирующие различные аспекты применения ассемблера. В качестве средств разработки примеров используются макроассемблер MASM 6.14 и Microsoft Visual C++ .NET 2003. Исходные тексты программ содержатся на прилагаемом к книге компакт-диске.

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

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

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

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

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

Mov приемник, источник

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

Mov edx, ecx

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

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

Mov al, ecx ; не правильно

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

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

Mov al, bl mov cl, dl mov cx, dx mov ecx, ebx

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

смещение 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:

Mov eax, dword ptr

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

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

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

Mov cl, byte ptr ; cl получит значение 0Dh mov dx, word ptr ; dx получит значение 7DEFh

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

Byte - 1 байт Word - 2 байта Dword - 4 байта

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

Mov eax,

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

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

Mov edx, 5006h

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

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

Mov eax, 403045h ; пишет в eax значение 403045 mov cx, ; помещает в регистр CX значение (размера word) из памяти; указанной в EAX (403045)

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

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

(1) mov ecx, 100 (2) mov eax, 200 (3) push ecx ; сохранение ecx (4) push eax (5) xor ecx, eax (6) add ecx, 400 (7) mov edx, ecx (8) pop ebx (9) pop ecx

  • 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 стоит в том месте, на которое он указывает)

Mov ax, 4560h push ax mov cx, FFFFh push cx pop edx edx теперь 4560FFFFh.

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

Code.. call 0455659 ..more code.. Код с адреса 455659: add eax, 500 mul eax, edx ret

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

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

Push значение_1 push значение_2 call procedure

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

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

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

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

Назад | Оглавление |

Оставить комментарий

Комментарии

стёк растёт в низ и чем он больше тем ESP меньше

То есть как то так?:
|| типа пустой стёк
V
| |ESP
| |6
| |5
| |4
| |3
| |2
| |1
| |0

После кода
push 0fh
push 0ffh

|| типа стёк
V
|0fh|7
|0ffh|6
| |ESP
| |4
| |3
| |2
| |1
| |0

Если это так то
какое значение имеет ESP когда стёк пуст?

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

1. Ревич Ю. – Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера, 2014 г.

«Свежая кровь» в области программирования микроконтроллеров. Подробно изложены особенности Atmel AVR, есть перечень команд и готовые рецепты – ассемблер на примерах. Хорошая вещь для радиолюбителей и инженерно-технических работников, хотя подойдет и начинающим кодерам: затронуты история, семейства и возможности МК AVR. Стоит отметить, что введение лаконичное, быстро перетекающее в суть, поэтому сетовать на лирику не придется.

2. Калашников О. – Ассемблер – это просто. Учимся программировать, 2011 г.

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

3. Аблязов Р. – Программирование на ассемблере на платформе x86-64, 2011 г.

Акцент делается на работе процессора в защищенном режиме и long mode. Это незаменимая база для программирования в Win32 и Win64, которая затрагивает команды ассемблера, прерывания, механизмы трансляции и защиты с учетом режимных отличий. Рассматривается разработка оконных приложений и драйверов. Данный ассемблер учебник подойдет начинающим кодерам и тем, кто сразу перешел к программированию на ассемблере, но плохо разобрался в аппаратной платформе x86-64.

4. Столяров А. – Программирование на языке ассемблера NASM для ОС Unix, 2011 г.

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

В современных операционных система задания по ВССиТ выполнять, мягко говоря проблематично. Для написания контрольных, да и просто освоения начальных навыков необходимо разобраться с компилятором MASM или TASM которые работают из под DOS.
Сами компиляторы, линковщики и все другие приблуды можно найти, например, на http://kalashnikoff.ru/ или http://www.wasm.ru/ . А тут будет рассказываться о том, что ближе к телу.

Необходимые инструменты и их настройка.

И так, что нам нужно. Нам нужен эмулятор DOS-терминала и компилятор. Компилятор я выбрал MASM 6.11, так как им до этого пользовался, и кое что в моей памяти уже было.Как DOS-эмулятор я советую DOSBox. Версии есть и под Windows и под Linux. Под Linux его можно установить из стандартного репозитория. Для Ubuntu:
$sudo apt-get install dosbox или из Центра приложений.
После запуска вы увидите экран с приглашением:
Z:\> Смонтируйте диск C:\ для этого наберите:
Z:\>mount c /home/user/folder_prodject И перейдите в неё:
Z:\>c: командой dir вы сможете посмотреть содержание директории, а командой cd имя_директории перейти в другую папку находящуюся в точке монтирования или в её подпапках.
Пример на моем проекте:


Если вы работаете много в DOS-эмуляторе, то такой способ может оказаться не очень удобным. Но моно настроить автоматическое монтирование диска C:\
Открываем /home/user/.dosbox/dosbox-0.74.conf в редакторе, и ищем строки:
# Lines in this section will be run at startup. # Yju can put your MOUNT lines here. и пишем тут что-то типа:
mount C /home/user/asm PATH=%PATH%;C:\masm611\bin\ C: При старте будет монтироваться C:\ диск в /home/user/asm, при этом эта директория должна существовать. PATH назначает пути поиска программ, это нужно что бы нам не мусорить в одной директории, а была возможность разнести компилятор и проект в разные. В конце стоит C: что бы DOSBox самостоятельно переводил нас на диск C:\ и берег наши телодвижения.


На последнем рисунке показана команда cd и dir, обратите внимание на то как отражаются имена файлов написанных русскими буквами. Возможно это и лечиться, но нужно ли это нам? И не забывайте, что MS-DOS использовал название файлов в формате 8.3. То есть, на имя отводилось 8 символов, потом шла точка (.), а затем расширение файла. При других названиях тоже могут возникнуть проблемы.

Как использовать MASM 6.11.

Теперь разберем как нам компилировать код, который мы напишем.
C:\>ml /с имя_файла.asm получим файл имя_файла.obj Ключ /c говорит компилятору не проводить линковку.
C:\>link имя_файла.obj получим исполняемый файл.
Но можно сделать всё быстрее:
C:\>ml имя_файла.asm /AT При этом мы получим и.obj файл и исполняемый.com. Флаг /AT говорит компилятору вызвать линковщик и передает ему флаг /T который обозначает модель TINY.
Ещё часто бывает нужен файл листинга программы, для этого используйте ключ /Fl:
C:\>ml имя_файла.asm /Fl Файл листинга будет записан в имя_файла.lst

Пишем программку.

Всё, на этом самое сложное закончилось. Теперь начинаем писать программу на ассемблере.
Так как в задачах часто просят вывести решение формул на экран, то и будем разбирать подобный пример. Сумма делений с x= от 1 до 10:

Основные команды которые будем использовать

Регистры, ох уж эти регистры. Краткий экскурс.

Сейчас, что бы начать читать код, достаточно знать регистры общего назначения:
Они могут быть 8 битные (например, al, ah), 16 битные (например, ax) и 32 битные (например, eax).
Все 16 битные регистры делятся на на младший и старший, например, ax делиться на al и ah. Делиться значит состоит, а не математическое действие.
eax, ax, al - очень часто выступают как приёмник значений, например, при умножении и делении.
ebx, bx. bl, bh - свободный регистр, который можно использовать в хвост и гриву.
edx, dx - часто используется для пересылки дополнительной информации или остатка от деления.
ecx, cx - называется счетчик, используется в циклах.
Всё остальное в комментариях программы. Кстати точка с запятой (;) используется как команда начать комментарий, и всё что написано за ней в строке не интерпретируется компилятором

Тренируемся

Первое что нам нужно - это разложить наш пример на простые составляющие, что бы составить алгоритм. К примеру: x в кубе - это x*x*x. Вспоминаем: умножение это mul, то есть мы можем это записать:
mov ax,1 ; присвоили значение mul ax ; умножили первый раз, то есть возвели в квадрат mul ax ; умножили второй раз, то есть возвели в куб Вот, так пошагово это и происходит.

А теперь сам листинг решения примера:

.MODEL tiny ; задаём модель в данном случае.com .CODE .486 ; указываем модель процессора org 100h ; выделяем память start: mov ecx,10 ; задаём количество циклов. 10 потому, что у нас x от 1 до 10 Lb1: ; устанавливаем метку для цикла mov eax,11 ; находим х sub eax,ecx ; x=11-число циклов (1, 2, 3... 11-1=10) push ecx ; сохраним в стеке сх для использования в цикле push eax ; сохраним в стеке ax что бы больше не высчитывать его mul eax ; x^2 (^ - будет означать "в степени") mov ecx,eax ; сохраним eax в ecx потом отнимать нужно будет mov ebx,3 ; ebx = 3 mul ebx ; 3x^2 sub eax,1 ; 3x^2-1 mov ebx,eax ; сохраняем eax в ebx потом понадобиться pop eax ; восстанавливаем eax так как уже нужен eax опять = x push ebx ; и сохраняем ebx так как потом понадобиться mov ebx,eax ; ebx = eax mov eax,ecx ; помните ecx=x^2, теперь eax = ecx, но можно было просто перемножать mul ebx ; eax = x^3 mov ebx,4 ; ebx = 4 mul ebx ; eax = 4x^3 sub eax,ecx ; eax = 4x^3-x^2 add eax,2 ; eax = 4x^3-x^2+2 pop ebx ; восстанавливаем ebx mov a,eax ; делимое (a - это переменная) mov z,ebx ; делитель (z - это тоже переменная) описаны в конце программы finit ; инициализируем сопроцессор fld a ; делимое в сопроцессор fdiv z ; проводим деление в сопроцессоре call tEnter ; это вызов функции которая переводит строку call pFloat ; выводим результат деления в консоль @4: fadd t ; добавляем предыдущий результат деления, для получения суммы; значений функции (t - это переменная) fst t ; запоминаем сумму в переменной pop ecx ; вынимаем ecx из памяти для корректной работы цикла loop Lb1 ; переходим на метку Lb1 пока ecx не станет равным нулю call pEnter ; это вызов функции которая переводит строку call pFloat ; выводим sum((4x^3-x^2+2)/(3x^2-1)) при x от 1 до 10 с шагом 1 int 20h ; Завершение работы программы (это называется; вызвать прерывание 20h) ret ; конец блока; дальше начинается настоящее колдовство;выводит целое число pInt: pushad ; сохраняем все регистры mov bx,sp ; bx = sp mov byte ptr ss:,"$" ; символ конца строки @1:cdq ; метка цикла. и команда cdq копирует знаковый бит регистра eax на; все биты регистра edx div ecx ; делим число на основание edx - остаток, eax - частное add dl,"0" ; преобразование в ASCII dec bx ; уменьшаем bx на 1 mov ss:,dl ; добавляем в стоку перед предыдущим test eax,eax ; проверяем есть ли в eax ещё что-нибудь jne @1 ; если есть повторяем цикл mov ax,ss ; выводим строку на экран mov ds,ax ; ds = ax dec bx ; уменьшаем bx на 1 mov dx,bx ; dx = bx xchg sp,bx ; если не обменять вылезет мусор mov ah,9 ; номер функции прерывания int 21h ; вызываем прерывание xchg sp,bx ; если не обменять программа завершиться popad ; восстанавливаем данные из стека ret ;выводит число pFloat: pushad ; сохраняем все регистры mov ecx,10 ; задаём основание системы счисления push ecx ; сохраняем основание mov bp,sp ; bp = sp fst dword ptr ss: ; выводим из сопроцессора как двойное слово в регистр ss xor eax,eax ; обнуляем eax (xor бинарное или) mov edx,ss: ; edx = ss: shl edx,1 ; сдвигаем в edx все биты на 1 влево mov ecx,edx ; ecx = edx shr ecx,24 ; сдвигаем в ecx все биты в право на 24 sub cx,126 ; вычитаем их cx 126 - Порядок (экспонента) shl edx,7 ; сдвигаем edx влево на 7 or edx,80000000h ; значащие биты (мантисса) shld eax,edx,cl ; eax - целая часть shl edx,cl ; edx - дробная часть pop ecx ; сохраняем ecx call pInt ; выводим на экран целую часть;выводим на экран дробную часть xchg eax,edx ; обмениваемся значениями cdq ; преобразуем двойное слово в четверное sub bp,28 ; вычитаем из bp 28 mov byte ptr ss:,"." ; добавляем разделитель десятичной дроби @2:mul ecx ; умножаем на основание 10 add dl,"0" ; преобразование в ASCII inc bp ; увеличиваем bp на единицу mov ss:,dl ; добавляем в строку test eax,eax ; проверяем есть ли ещё знаки после запятой jne @2 ; да? повторяем цикл mov byte ptr ss:,"$" ; нет? добавляем знак конца строки, иначе выведет мусор sub sp,32 ; приводим строку в нормальное состояние push ss pop ds mov dx,sp ; помещаем в dx откуда её и будем печатать mov ah,9 ; функция прерывания прерывания int 21h ; вызов прерывания call nEnter ; вызов функции перевода строки add sp,32 ; восстанавливаем sp popad ; восстанавливаем регистры ret ;вспомогательная функция - переводит строку nEnter: pushad mov dx,offset str0 mov ah,9 int 21h popad ret ;вспомогательная функция, печатает строку "Temp rezult:" tEnter: pushad mov dx,offset str1 mov ah,9 int 21h popad ret ;вспомогательная функция, печатает строку "Result:" pEnter: pushad mov dx,offset strE mov ah,9 int 21h popad ret ;переменные a dd ? z dd ? t dd 0 str0 db 10,13,"$" str1 db "Temp result: ","$" strE db 10,13,"Result: ","$" end start ; конец программы

Рекомендуем почитать

Наверх