assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 38
Текст из файла (страница 38)
Работа этой команды зависитот атрибута размера сегмента:ш use 16 — в стек записывается регистр FLAGS размером два байта;я use3 2 — в стек записывается регистр Е FLAGS размером четыре байта.Команда PUSHFW сохраняет в стеке регистр флагов размером в слово. С атрибутом use!6 всегда работает так же, как команда PUSHF.Команда PUSHFD сохраняет в стеке регистр флагов FLAGS или EFLAGS в зависимости от атрибута размера сегмента (то есть то же, что и PUSHF).Следующие три команды также выполняют действия, обратные действиям рассмотренных выше команд:Ш POPF;* POPFW;и POPFD.Работать со стеком приходится постоянно, поэтому к этому вопросу мы будемвозвращаться еще не раз. Отметим основные виды операций, когда использованиестека практически неизбежно:ш вызов подпрограмм;II временное сохранение значений регистров;« определение локальных переменных в процедуре.Итоги* Основная команда пересылки данных — MOV. Операнды этой команды (каки большинства других команд, берущих значения из памяти) должны бытьсогласованы по разрядности.
Хотя обычно действуют правила умолчания, в сомнительных ситуациях лучше явно указывать разрядность операндов с помощью оператора PTR.Ш Управление периферией компьютера в общем случае осуществляется с использованием всего двух команд ввода-вывода — IN и OUT.ii В процессе работы программы динамически можно получить как эффективный, так и полный (физический) адрес памяти. Для этого язык ассемблера предоставляет группу команд получения указателей памяти.8 Архитектура процессора предоставляет в распоряжение программиста специфическую, но весьма эффективную структуру — стек. Система команд поддерживает все необходимые операции со стеком.
Подробнее со стеком мы познакомимся при изучении модульного программирования на ассемблере.Глава 8Арифметические командыФорматы арифметических данныхАрифметические операции над двоичными числамиАрифметические операции над десятичными (BCD)числамиОдной из причин, постоянно заставляющих человека совершенствовать средствадля выполнения вычислений, — желание эффективно, быстро и без ошибок решать различные счетные задачи.
Для начала мечтой людей была автоматизациявыполнения простейших арифметических действий. Первая реализованная попытка — начало XVII в., 1623 г. Ученый В. Шикард создает машину, умеющую складывать и вычитать числа. Знаменитый французский ученый и философ Блез Паскаль в 1642 г. изобрел первый арифмометр, основным элементом в котором былозубчатое колесо. Изобретение этого колеса уже само по себе было ключевым событием в истории вычислительной техники, подобно лампам и транзисторам в нашевремя.
Правнуки этого колеса еще совсем недавно, каких-нибудь два-три десяткалет назад, использовались в арифмометрах (соответствующая модель была создана в 1842 г.) на столах советских бухгалтеров. Тот, кому довелось поработать наэтих арифмометрах, вряд ли вспомнят о высокой эффективности вычислительного процесса — слишком велика была зависимость от человеческого фактора. Снизить эту зависимость удалось лишь в середине прошлого века, когда появилисьпервые ЭВМ на лампах, потом на транзисторах и, наконец, на микросхемах различной интеграции. Таким образом, путь к эффективному автоматизированномурешению для проведения расчетов растянулся почти на три столетия.
Тем не менее, именно благодаря стремлению разгрузить голову от рутины человек имеетсегодня определенные достижения в области компьютерной техники.Любой компьютер, от самого примитивного до супермощного, имеет в своейсистеме команд команды для выполнения арифметических действий. Работая166Глава 8. Арифметические командыс компьютером при помощи языков высокого уровня, мы воспринимаем возможность проведения расчетных действий как нечто должное, забывая при этом, чтокомпилятор даже очень развитого языка программирования превращает все самые высокоуровневые действия в унылую последовательность машинных команд.Конечно, мало кому придет в голову писать серьезную расчетную задачу на ассемблере. Но даже в системных программах часто требуется проведение небольшихвычислений.
Поэтому важно разобраться с этой группой команд. К тому же она, наудивление, очень компактна и не избыточна.Процессор может выполнять целочисленные операции и операции с плавающей точкой. Для этого в его архитектуре есть два отдельных устройства, каждое изкоторых имеет свою систему команд. В принципе, целочисленное устройство может взять на себя многие функции устройства с плавающей точкой, но это потребует больших вычислительных затрат. Устройство с плавающей точкой и его система команд будут рассмотрены в главе 17. Для большинства задач, использующихязык ассемблера, достаточно целочисленной арифметики.ОбзорЦелочисленное вычислительное устройство поддерживает чуть больше десяткаарифметических команд.
На рис. 8.1 приведена классификация команд этойгруппы.Целочисленныеарифметическиекоманды1Преобразованиятипов- cbw- cwd- cwde- cdq- movsx- movzx1ДвоичнойарифметикиСложение-add-adc•нпс1КоррекциясложенияLaaaLdaaКоррекциявычитанияВычитание-sub-sbb-dec• Умножение-imul-mul• Деление-idiv-div(ИзменениезнакаLneg1Десятичнойарифметики |taasdasКоррекцияумноженияLaam1|ВспомогательныекомандыL-bswapПрочие командыс арифметическимпринципом действия-стр-cmpxchg-set ccLxaddКоррекцияделения|-aadРис.
8.1. Классификация арифметических командОбзор167Группа арифметических целочисленных команд работает с двумя типами чисел:* целыми двоичными числами, которые могут иметь или не иметь знаковый разряд, то есть быть числами со знаком или без знака;Я целыми десятичными числами.В главе 3 мы обсуждали вопрос о форматах данных, поддерживаемых архитектурой IA-32. Рассмотрим теперь форматы данных, с которыми работают арифметические команды.Целые двоичные числаЦелое двоичное число — это число, закодированное в двоичной системе счисления.В архитектуре IA-32 размерность целого двоичного числа может составлять 8, 16или 32 бита.
Знак двоичного числа определяется тем, как интерпретируется старший бит в представлении числа. Это 7-й, 15-й или 31-й биты для чисел соответствующей размерности (см. главу 5). При этом интересно то, что среди арифметических команд есть всего две, которые действительно учитывают этот старшийразряд как знаковый, — это команды целочисленного умножения IMUL и деленияIDIV. В остальных случаях ответственность за действия со знаковыми числами и,соответственно, со знаковым разрядом ложится на программиста. К этому вопросу мы вернемся чуть позже.
Диапазон значений двоичного числа зависит от егоразмера и трактовки старшего бита либо как старшего значащего бита числа, либокак бита знака числа (табл. 8.1).АвтоQNai щ| ж1а AlУИ« .edit УД«М„»З» Bcgakpo3.nt8,-,-Oata,.Module: pcg_8_l File: C:\TASM\WORK\prg_8_l.asm 15;pcg_8_l.asmmasmmodel smallstack 256j—[Bl-Dumpds:0000 17 80 26 BD BO 96 00.data ;сегмент данныхpec_l db 23ds:0008 74 00 00 00 00 00 00ds:0010 00 00 00 00 00 00 00pec_2 dw 9856pec_3 dd 9875645ds:0018 00 00 00 00 00 00 00pec_4 dw 29857Al000000.code ;сегмент кодаmain: ;точка входа в программуmov ax,@data ;связываем регистр dx с сегментомmov ds,ax ;данных через регистр ахexit:;посмотрите в отладчике дамп сегмента данныхmovax,4cOOh стандартный выходint21hend main;конец программыРис.
8.2. Дамп памяти для сегмента данных листинга 8.1-3-ttl Ul6168Глава 8. Арифметические командыТаблица 8.1. Диапазон значений двоичных чиселРазмерность поляБайтСловоДвойное словоЦелое без знака0...2550...65 5350...4 294 967 295Целое со знаком-128...+ 127-32 768...+32 767-2 147 483 64S...+2 147 483 647Как описать целые двоичные числа в программе? Это делается с использованием директив описания данных DB, DW и DD. В главе 5 описаны возможные вариантысодержимого полей операндов этих директив и диапазоны их значений.
К примеру, последовательность описаний двоичных чисел из сегмента данных листинга 8.1(помните о принципе «младший байт по младшему адресу») будет выглядеть в памяти так, как показано на рис. 8.2.Листинг 8.1. Числа с фиксированной точкой;prg_8_l.asmmasmmodelsmallstack256.data;сегмент данныхper_l db 23per_2 dw 9856per_3dd 9875645per_4 dw 29857.code;сегмент кодаmain:;точка входа в программуmov ax,@data;связываем регистр dx с сегментомmov ds.ax;данных через регистр ахexit:;посмотрите в отладчике дамп сегмента данныхmov ax,4c00h;стандартный выходint 21hend main;конец программыДесятичные числаДесятичные числа — специальный вид представления числовой информации, в основу которого положен принцип кодирования каждой десятичной цифры числагруппой из четырех битов. При этом каждый байт числа содержит одну или дведесятичные цифры в так называемом двоично-десятичном коде (Binary-CodedDecimal, BCD).
Процессор хранит BCD-числа в двух форматах (рис. 8.3).• В упакованном формате каждый байт содержит две десятичные цифры. Десятичная цифра представляет собой двоичное значение в диапазоне от 0 до 9 размером четыре бита. При этом код старшей цифры числа занимает старшиечетыре бита. Следовательно, диапазон представления десятичного упакованного числа в одном байте составляет от 00 до 99.» В неупакованном формате каждый байт содержит одну десятичную цифру в четырех младших битах. Старшие четыре бита имеют нулевое значение.