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 =
