CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Выбор размера данных ----------------------------------------------------------------- В языке Ассемблера с помощью инструкции MOV можно копировать байты или значения размером в слово. Давайте рассмотрим, каким образом Турбо Ассемблер определяет, с каким размером данных нужно работать. Во многих случаях операнды явным образом указывают Турбо Ас- семблеру, каким должен быть размер данных. Если в инструкции ис- пользуется регистр, то размер данных должен соответствовать раз- меру этого регистра. Например, размер данных в следующих инструк- циях ясен: . . . mov al,1 ; байт mov dx,si ; слово mov bx,[dl] ; слово mov [bp+si+2],al ; байт . . . Аналогично, именованные ячейки памяти имеют заданные разме- ры, поэтому размер данных в следующих инструкциях для Турбо Ас- семблера ясен: . . . .DATA TestChar DB ? TempPointer DW TestChar . . . .CODE . . . mov [TestChar],'A' mov [TempPointer],0 . . . Однако, иногда приходится иметь дело с инструкциями MOV, в которых размер данных не определен. Например, Турбо Ассемблер не может сделать вывод о том, следует ли в следующей инструкции за- писать значение размером в слово или в байт: mov [bx],1 Фактически, Турбо Ассемблер не будет знать, как такую инст- рукцию нужно ассемблировать. Было бы удобно иметь возможность временного доступа к переменой размером в слово, как к байту, и наоборот. Турбо Ассемблер дает вам способ гибкого определения размера данных в виде операций WORD PTR и BYTE PTR. Операция WORD PTR указывает Турбо Ассемблеру, что данный операнд в памяти нужно ин- терпретировать, как операнд размером в слово, а операция BYTE PTR указывает Турбо Ассемблеру, что данный операнд в памяти нужно ин- терпретировать, как операнд размером в байт, независимо от его предопределенного размера. Например, можно сделать так, что в последнем примере значение 1 размером в слово будет записываться в слово, на которое указывает регистр BX: mov WORD PTR [bx],1 или же можно сделать так, что в данном примере значение 1 разме- ром в байт будет записываться в байт, на который указывает ре- гистр BX: mov BYTE PTR [bx],1 Заметим, что операции WORD PTR и BYTE PTR, если их применять к регистрам, не имеют смысла, так как регистры всегда имеют фик- сированный размер. В таком случае операции BYTE PTR и WORD PTR игнорируются. Аналогично, эти операции игнорируются при примене- нии к константам, поскольку они всегда имеют тот же размер, что и операнд-приемник. Операции WORD PTR и BYTE PTR имеют другое назначение: их можно использовать для временного выбора размера данных для име- нованной переменной в памяти. Почему это может оказаться полезным? Рассмотрим следующий пример: . . . .DATA Source1 DD 12345h Source2 DD 54321h Sum DD ? . . . .CODE . . . mov ax,WORD PTR [Source1] ; получить младшее ; слово Source1 mov dx,WORD PTR [Source1+2] ; получить старшее ; слово Source1 add ax,WORD PTR [Source2] ; прибавить к Source2 ; младшее слово adc dx,WORD PTR [Source2+2] ; прибавить к Source2 ; старшее слово mov WORD PTR [Sum],ax ; сохранить младшее ; слово суммы mov WORD PTR [Sum+2],dx ; сохранить старшее ; слово суммы . . . Все переменные, которые используются в данном примере, представляют собой длинные целые или двойные слова. Однако, про- цессор 8086 не может выполнять сложение двойных слов непосредс- твенно, поэтому такое сложение приходится разбивать на ряд опера- ций со словами. Операция WORD PTR позволяет обращаться к частям переменных Source1, Source2 и Sum, как к словам, хотя сами эти переменные представляют собой двойные слова. Операции FAR PTR и NEAR PTR хотя и не влияют непосредственно на размер данных, они аналогичны операциям WORD PTR и BYTE PTR. Операция FAR PTR приводит к тому, что целевая метка инструкции перехода или вызова будет интерпретироваться, как дальняя метка, и при этом будут загружаться оба регистра CS и IP. С другой сто- роны, операция NEAR PTR вынуждает интерпретировать соответствую- щую метку, как метку ближнего типа, переход на которую осуще- ствляется путем загрузки одного регистра IP. Данные со знаком и без знака ----------------------------------------------------------------- И числа со знаком, и беззнаковые числа состоят из последова- тельности двоичных цифр. Ответственность за различие этих двух видов чисел возлагается на программиста, который пишет программу на Ассемблере (то есть на вас), а не на процессор 8086. Например, значение 0FFFFh может представлять собой либо 65535, либо -1, в зависимости от того, как ваша программа его интерпретирует. Откуда вы знаете, что 0FFFFh - это -1? Прибавьте к нему 1: . . . mov ax,0ffffh add ax,1 . . . и вы обнаружите, что результат будет равен 0. Как раз такой ре- зультат должен получиться при сложении -1 и 1. Одна и та же инструкция ADD будет работать одинаково хорошо, независимо от того, представляют ли собой операнды значения со знаком или беззнаковые значения. Предположим, например, что вы вычли из 0FFFFh значение -1 следующим образом: . . . mov ax,offffh sub ax,1 . . . Результат при этом был бы равен 0FFFEh, что представляет со- бой 65534 (беззнаковое число) или -2 (число со знаком). Если это кажется непонятным, прочитайте одну из книг, реко- мендуемых в конце данного руководства (или одну из книг по Ас- семблеру, изданных в СССР, например книгу Бредли). Это позволит вам больше узнать об арифметике с дополнением до двух - средстве, с помощью которого процессор 8086 обрабатывает числа со знаком. К сожалению, мы не располагаем здесь местом, чтобы подробно расска- зать об арифметике значений со знаком, хотя для программиста это представляет собой одну из важных тем, которую нужно хорошо пони- мать. Пока же запомните, что инструкции ADD, SUB, ADC и SBB рабо- тают одинаково хорошо как с беззнаковыми значениями, так и со значениями со знаком, поэтому для таких операций не требуется специальных инструкций сложения или сочетания. Знак имеет значе- ние в операциях умножения или деления (как вы увидите далее), а также при преобразовании размеров данных. TASM2 #1-5/Док = 204 =