Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
flor_apparato-orientirovnnoe_prog.doc
Скачиваний:
89
Добавлен:
15.06.2014
Размер:
926.72 Кб
Скачать

3.5. Неарифметические операции над кодами

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

Для выполнения поразрядной логической операции И служит команда с мнемокодом AND, имеющая общий вид

AND операнд1, операнд2

Основное практическое применение эта команда имеет с константным вторым операндом, который в этом случае называют маской логической операции. Команда AND с маской применяется для выборочного сброса в нуль отдельных битов двоичного кода первого операнда. (Такое действие основано на обычных, хорошо известных свойствах логической операции И: x&0=0, x&1=x.) Например, команда

AND al, 3Fh

сбрасывает в нуль два старших бита двоичного кода в регистре AL

Для выполнения поразрядной логической операции ИЛИ служит команда с мнемокодом OR, имеющая общий вид

OR операнд1, операнд2

Основное практическое применение эта команда имеет также с константным вторым операндом - маской логической операции ИЛИ. Команда OR с маской применяется для выборочной установки (в единицу) отдельных битов двоичного кода первого операнда. (Такое действие основано на обычных, хорошо известных свойствах логической операции И: x0=x, x1=1.) Например, команда

OR dx, 8001h

устанавливает в единицу старший и младший биты двоичного кода в регистре DX.

Менее употребительной является команда исключающего ИЛИ, задаваемая мнемокодом XOR и употребляемая обычно также с константой - маской в качестве второго операнда. В общем случае она имеет вид

XOR операнд1, операнд2

и служит для обращения (инверсии) тех двоичных разрядов первого операнда, которым соответствуют единичные биты во втором операнде.

Последняя из логических команд выполняет операции поразрядного инвертирования двоичного кода единственного ее операнда и имеет вид

NOT операнд

Команды сдвига представлены множеством модификаций. Основными в большинстве применений являются команды с мнемокодами SHL и SHR, наименования которых восходят к английским словам Shift, Left и Right. Эти команды задают сдвиг двоичного кода в первом операнде на число разрядов, заданное во втором операнде. В настоящее время основными формами этих команд являются задаваемые следующими схемами:

SHL операнд1, число

SHR операнд1, число

Биты, вдвигаемые в этих командах, всегда нулевые. Кроме перечисленных команд имеются еще команды арифметического сдвига SAL, SAR и циклического сдвига ROL, ROR, RCL, RCR. Из-за редкого их использования они не будут рассматриваться в данном пособии.

Далее в листинге 3.5.1 приведена программа, демонстрирующая материал разделов 3.4 и 3.5. В этой программе содержатся подпрограммы вывода на экран содержимого регистров AL, AX и EAX в виде шестнадцатеричных представлений. Причем процедура call wrhex_hal отображает на экране значение только младшей половины регистра AL, выдавая его всегда в виде одной шестнадцатеричной цифры, процедура wrhex_al выдает содержимое регистра AL в виде двух шестнадцатеричных цифр, процедура wrhex_ax выдает содержимое регистра AX в виде четырех шестнадцатеричных цифр, а процедура wrhex_eax выдает содержимое регистра EAX в виде восьми шестнадцатеричных цифр.

; Использование процедур.

GLOBAL _start

SEGMENT .text

_start: mov al, 0d5h

call wrhex_hal

call wrcrlf

mov al, 0fah

call wrhex_al

call wrcrlf

mov ax, 05e7bh

call wrhex_ax

call wrcrlf

mov eax, 03fec5e7bh

call wrhex_eax

call wrcrlf

mov eax,1

int 80h ; function=exit for Linux

;procedure wrcrlf

wrcrlf:

pusha

mov eax,4 ; N function=write

mov ebx,1 ; N handle=1 (stdout)

mov edx,1 ; number of byte

mov ecx, crlf ; address of crlf

int 80h

popa

ret

; end procedure wrcrlf

;procedure wrhex_hal

wrhex_hal: push eax

push ebx

push ecx

push edx

and al, 0Fh

cmp al, 10

jge hexa

add al, '0'

jmp wrchar

hexa: add al,'A'-10 ; из AL вычесть 10 и прибавить значение 'A'

wrchar:

mov [cha],al

mov eax,4 ; N function=write

mov ebx,1 ; N handle=1 (stdout)

mov edx,1 ; number of byte

mov ecx, cha ; address of cha

int 80h

pop edx

pop ecx

pop ebx

pop eax

ret

; end procedure wrhex_hal

; procedure wrhex_al

wrhex_al: push eax

shr al,4

call wrhex_hal

pop eax

call wrhex_hal

ret

; end procedure wrhex_al

; procedure wrhex_ax

wrhex_ax: push eax

shr ax,8

call wrhex_al

pop eax

call wrhex_al

ret

; end procedure wrhex_ax

; procedure wrhex_eax

wrhex_eax: push eax

shr eax,16

call wrhex_ax

pop eax

call wrhex_ax

ret

; end procedure wrhex_eax

SEGMENT .data

crlf db 10

cnt dd 0

cha db 0

Листинг 3.5.1. Вывод шестнадцатеричного значения из регистров AL, AX, EAX

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

Во всех приведенных процедурах используется сохранение регистров и восстановление их из стека, причем в процедуре wrcrlf для этого применены универсальные команды PUSHA и POPA, а в остальных процедурах сохраняются и восстанавливаются только действительно изменяемые в них регистры.

Основную работу для всех процедур выполняет подпрограмма wrhex_hal, предназначенная для вывода значения младшей половины регистра AL в виде одной шестнадцатеричной цифры. В ее начале содержимое регистра AL изменяется обнулением битов в старшей половине регистра. Для этих целей использована команда логического поразрядного умножения на константу 0fh. После этого выполняется сравнение промежуточного результата (значения младшей половины) с константой 10.

Если рассматриваемое значение меньше 10, то шестнадцатеричная цифра представляется обычной десятичной цифрой, и в этом случае используется уже изученная выше технология получения выводимой цифры путем прибавления к ее значению кода цифры '0'. В противном случае следует вычесть из промежуточного результата значение 10, получив тем самым числовое смещение требуемого кода от самой меньшей по значению шестнадцатеричной цифры, отличной от арабстких, и изображаемой буквой 'A'. Затем добавить к очередному результату значение кода буквы 'A' (что и порождает код шестнадцатеричной цифры, изображаемой соответствующей буквой). Две последние операции оказалось возможным объединить в одну с помощью команды

add al,'A'-10

которая прибавляет к промежуточному значению в регистре AL значение константы, сформированной из разности кода буквы 'A' и числа 10.

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

Процедура wrhex_al строится уже проще на основе использования процедуры wrhex_hal. В начале из аргумента - регистра AL - сдвигом на 4 бита в младшую половину регистра помещается его бывшая старшая половина. Затем обращением call wrhex_hal на экран выводится шестнадцатеричная цифра, отвечающая значению этой старшей половины. Потом в регистре AL восстанавливается первоначальное значение, бывшее в нем при обращении к данной подпрограмме call wrhex_hal. С этой целью ранее запомненное для сохранения значение всего регистра EAX восстанавливается командой pop eax. Далее опять вызывается подпрограмма wrhex_hal, которая выводит в виде шестнадцатеричной цифры значение младшей половины регистра AL. Тем самым отображаются обе шестнадцатеричные цифры значения всего регистра AL, причем в правильном порядке. Заметим, что какое-либо восстановление регистров после последнего вызова уже не требуется, так как после восстановления значения регистра EAX никаких изменений регистров в текущей процедуре wrhex_al не происходит. Это демонстрирует, что общее правило восстановления регистров может в конкретных ситуациях видоизменяться.

Процедуры wrhex_ax и wrhex_eax построены очень похоже на процедуру wrhex_al, они отличаются только тем, что на первом этапе содержимое регистров, соответственно, AX и EAX сдвигается на 8 и 16 битов. Тем самым вначале задается для промежуточного вывода старшая половина соответствующего регистра, а затем, после восстановления значения регистра eax, используется отображение содержимого младшей половины этого регистра. Отображения же указанных половин выполняются вызовом, соответственно, процедур wrhex_al и wrhex_ax.

В основной части программы после занесения в регистры AL, AX и EAX констант 0fah, 05e7bh, 03fec5e7bh осуществляются вызовы, соответственно, процедур wrhex_al, wrhex_ax и wrhex_eax, что обеспечивает демонстрацию использования этих процедур.

Упражнения

1. Разработать подпрограмму, которая считывает последовательно десятичные цифры со стандартного ввода до тех пор, пока не встретится символ, отличный от цифры. Читаемая таким образом последовательность десятичных цифр должна преобразовываться в соответствующее двоичное значение, возвращаемое подпрограммой в регистре EAX в качестве результата.

2. Использовать подпрограмму предыдущего упражнения для ввода двух десятичных чисел, задаваемых со стандартного ввода; выполнить сложение этих чисел в основной части программы и затем, переписав основную преобразующую последовательность команд из листинга 3.3.1 в виде подпрограммы, обращением к последней вывести полученную сумму.

Соседние файлы в предмете Системное программное обеспечение