Chapter_09 (1110561)
Текст из файла
Глава 9. Дополнительные возможности Ассемблера9.1. Строковые командыСейчас мы изучим весьма полезный для понимания архитектуры нашего компьютера форматкоманд память-память (формат SS). До сих пор для работы с переменными в оперативной памяти мыиспользовали формат команд регистр-память (или память-регистр), при этом один из аргументов находился на регистре центрального процессора.
Например, для присваивания переменной Y значенияпеременной X вместо команды пересылки формата память-памятьmov Y,X; такого формата нетнам приходилось использовать две команды пересылки, напримерmov ax,Xmov Y,axЭто не всегда практично, если мы не предполагаем больше никаких операций с выбранным нарегистр операндом, тогда его пересылка из памяти на регистр оказывается лишним действием.1Именно для таких случаев и предназначены команды формата память-память, в некоторых случаяхони позволяют получать более компактные и быстрые программы.
В архитектуре нашего компьютера такие команды относятся к так называемым строковым или цепочечным командам (мы скоропоймём, почему они получили такое название).Строковые команды нашего компьютера хорошо использовать для обработки элементов массивов. Массивы коротких беззнаковых целых чисел могут трактоваться как строки (цепочки) символов,отсюда и название – строковые или цепочечные команды. Можно считать, что каждая строковаякоманда обрабатывает один элемент такого массива. При выполнении строковых команда в циклеполучается удобный способ обработки массивов, элементами которых являются короткие или длинные целые числа. Эти массивы могут располагаться в любом месте оперативной памяти.Знакомство со строковыми командами начнём с команд пересылки байта (movsb) или слова(movsw) с одного места оперативной памяти в другое.
Эти команды различаются только битом размера операнда w в коде операции. С битом w мы уже познакомились при изучении форматов командрегистр-регистр и регистр-память, w=0 для операндов-байтов и w=1 для операндов-слов. Командыmovsb и movsw не имеют явных операндов, их оба операнда op1 и op2 формата m8 (для w=0) иm16 (для w=1) заданы неявно (по умолчанию).Алгоритм выполнение команд movsb и movsw существенно зависит от так называемого флаганаправления DF (Direction Flag) из регистра флагов FLAGS. Для изменения значения этого флагаможно использовать команды cld (для операции очистки флага DF:=0), и std (для операции установки флага DF:=1).
Чтобы описания правил выполнения команд movsb и movsw были болеекомпактными и строгими, введём следующие условные обозначения:DFδ = (w+1)*(-1) ; φ(r16)={ r16 := (r16 + δ)mod 216 }Как видим, δ может принимать только значения ±1 и ±2, а оператор φ меняет величину заданного регистра r16 на значение δ. В этих обозначениях команды movsb и movsw выполняются последующему правилу:<es,di> := <ds,si>; φ(di); φ(si)Таким образом, неявный операнд op1 находится в памяти по адресу, заданному регистровой парой <es,di>, а неявный операнд op2 – по адресу <ds,si>, т.е. в общем случае операнды находятся в разных сегментах памяти.Для того, чтобы лучше понять логику работы описанной выше команды, рассмотрим широкораспространённую задачу пересылки массива целых чисел (и вообще данных) с одного места оперативной памяти в другое.
На языке Паскаль такая задача решается совсем просто, например:1Точнее, лишним будет только использование адресуемого регистра центрального процессора, их в распоряжении программиста и так немного (ax,bx и т.д.). Однако, как мы знаем, двухадресные команды форматапамять-память КОП оp1,op2 обязательно требуют для своего выполнения использования некоторых служебных регистров центрального процессора (напомним, что мы обозначали эти регистры как R1, R2 и S), ивыполняются, например, для команды сложения по схеме: R1:=op1; R2:=op2; S:=R1 + R2; op1:=S.2Var A,B: array[1..10000] of integer;. .
.B := A;Для языка Турбо-Паскаль, правда, это только частный случай задачи пересылки массива, так какв приведённом примере массивы A и B будут располагаться в одном сегменте данных. Общий случай пересылки массива на стандарте Паскале можно реализовать (для массива символов), например,в таком виде:Const N = 50000;Type Mas = Array[1..N] of char;VarA,B: ↑Mas;.
. .New(A); New(B);. . .B↑ := A↑;В этом примере динамические переменные (массивы символов, для Ассемблера, как мы знаем,это массивы коротких беззнаковых целых чисел) для нашей архитектуры обязательно будут располагаться в разных сегментах памяти (понять это!). А теперь рассмотрим реализацию похожей задачипересылки массива из одного места памяти в другое на языке Ассемблер (наши два массива будут нединамическими, а статическими, но так же располагаться в разных сегментах памяти).
Сначалаопишем два сегмента данных, в которых будут располагаться наши массивы A и B:ND1AD1D2BD2equ50000segment. . .dbN dup (?). . .endssegment. . .dbN dup (?). . .endsДля операции копирования желателен одновременный доступ к этим двум сегментам памяти,поэтому на начало сегмента D1 установим сегментный регистр ds, а на начало сегмента D2 – сегментный регистр es. Длину массива обозначим N, в частном случае длина массива может быть и нулевой (вспомним, какую важную роль в программах на Турбо-Паскале играли строки символов нулевой длины). Теперь фрагмент программы для реализации оператора присваивания B:=A может,например, иметь на Ассемблере такой вид:Code segmentassume cs:Code,ds:D1,es:D2,ss:StackStart:movax,D1movds,axmovax,D2moves,ax.
. .movsi,offset Amovdi,offset Bmovcx,Njcxz L1; при N=0L:moval,[si]moves:[di],alincsiincdiloop LL1:. . .3Оценим сложность нашего алгоритма пересылки массива. За единицу измерения сложностипримем операцию обмена данными и командами между центральным процессором и оперативнойпамятью. В нашем случае сложность алгоритма пересылки массива равна 7*N, где N – это длинамассива. Действительно, необходимо N чтений элементов массива из памяти на регистр al, N записей из этого регистра в память, и ещё нужно 5*N раз считать команды тела цикла из памяти на регистр команд в устройстве управления.Как видим, для пересылки целого числа из одного места памяти в другое нам понадобились двекомандыmov al,[si]mov es:[di],alтак как написать одну командуmov byte ptr[si],es:[di]нельзя – она требует несуществующего формата команды пересылки mov m8,m8 . Здесь, однако,хорошо подходит наша новая команда пересылки короткого целого числа movsb, с её помощьюзаключённый в рамку фрагмент предыдущей программы можно более компактно записать в виде:jcxz L1; при N=0cldL: movsbloop LТеперь в нашем цикле пересылки массива осталось всего две команды, следовательно, сложность нашего алгоритма снизилась до 4*N операций обмена с оперативной памятью.
Для дальнейшего ускорения выполнения таких циклов в язык машины была включена специальная команда цикла с кодом операции rep, которая называется префиксом повторения. Она похожа на командуцикла loop, но не имеет явного операнда – метки перехода на начало тела цикла. Эта метка не нужна, так как в теле цикла rep может находиться только одна, непосредственно следующая за ней команда, другими словами, пара командrep <строковая команда>выполняется по схеме 1while cx<>0 do begindec(cx); <строковая команда>end;С использованием этой новой команды цикла заключенный в рамку фрагмент нашей программыпересылки массива можно записать уже совсем кратко в виде:repcldmovsbЗаметим, что хотя rep и является служебным словом (кодом операции), но в программах егочасто пишут на месте метки (в качестве первого поля предложения Ассемблера), так как служебноеслово нельзя спутать с именем метки, заданным пользователем.
Пара команд rep movsb можетбыть вместе выбрана на регистр команд центрального процессора, так что теперь в цикле пересылки массива вообще нет необходимости обращаться в память за командами.2 Теперь сложность нашего алгоритма снизилась до теоретического минимума в 2*N операций, т.е. это позволило значительно поднять эффективность пересылки массива.3 Теперь Вам должно быть понятно, для чего це1Если за командой rep следует не строковая команда, а какая-нибудь другая, то команда rep просто игнорируется (выполняется так же, как и пустая команда с кодом операции nop, которая в нашей машине эквивалентна пустому оператору языка Паскаль).2Для продвинутых студентов: при возникновении прерывания между двумя выполняемыми командамирегистр IP (счётчик адреса) должен указывать на команду rep, так как на каждом шаге цикла она всегда будетвыполняться следующей.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.