Арифметические операции над целыми двоичными числами
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Сложение двоичных чисел без знака

inc операнд - операция инкремента, то есть увеличения значения операнда на 1;

inc ax; ax:=ax+1

inc x1

 

add оп1,оп2 - команда сложения с принципом действия: оп1 = оп1 + оп2 (addition)

add al, bl

add ax, 0fe2h

add ebx, x1+2

add x1, 0fh

add x2, ax

 

adc оп1,оп2 - команда сложения с учетом флага переноса cf. оп1 = оп1 + оп2 + знач_cf

 

Вычитание двоичных чисел без знака

dec операнд — операция декремента, то есть уменьшения значения операнда на 1;

dec cx ;cx:=cx-1

dec x

sub операнд_1,операнд_2 — команда вычитания; ее принцип действия:

операнд_1 = операнд_1 – операнд_2

sub al, bl; al:=al-bl

sub ax, x1

sub x2, dx

sub eax, 0f35h

sub x2, 22h

 

sbb операнд_1,операнд_2 — команда вычитания с учетом заема (флага cf ):

операнд_1 = операнд_1 – операнд_2 – значение_cf

Пример программы сложения двух однобайтных чисел.

model small .stack 100h .datax1      db   0c2hx2      db   022hy db   ? .code start: mov ax,@data mov ds,ax mov al, x1 add al, x2 mov y, al mov ax,4c00h int    21 h

End start

Умножение двоичных чисел

mul множитель_1 - операция умножения двух целых чисел без учета знака

Алгоритм работы:

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

 

mul dl; ax:=al*dl, dl- множитель_1 , al- множитель_2

mul x1; dx:ax=ax*0ad91h, x1 word- множитель_1 , ax- множитель_2

mul ecx; edx:eax=eax*ecx, ecx- множитель_1 , eax- множитель_2

 

imul множитель_1 - операция умножения двух целочисленных двоичных значений со знаком

 

Деление двоичных чисел

div делитель - выполнение операции деления двух двоичных беззнаковых значений

Алгоритм работы:

Для команды необходимо задание двух операндов — делимого и делителя. Делимое задается неявно и размер его зависит от размера делителя, который указывается в команде

 

div dl ;ah:al=ax/dl, ax –делимое, dl- делитель , ah-частное, al -остаток

div x1 ;ax:dx=dx:ax/0ad91h, dx:ax –делимое, x1 word- делитель , ax-частное,

;dx -остаток

div ecx ;eax:edx=edx:eax/ecx, edx:eax –делимое, ecx- делитель , eax-частное,

;edx -остаток

idiv делитель - операция деления двух двоичных значений со знаком

 

Пример программы умножения двух однобайтных чисел.

model small .stack 100h .datax1      db   78yl       db   ?yh      db   ? .code start: mov ax,@data mov ds,ax xor  ax, ax mov al, 25 mul x1 jnc   m1  ;если нет переполнения mov yh,ahm1:    mov yl, al mov ax,4c00h int   21h

end start


Пример. Вычислите следующее выражение у=(х2-х3)/х1, х1,х2,х3 - однобайтные числа


Model    small

Stack    100h

Data

s1 db 'Введите х1',10,13,'$'

s2 db 'Введите х2',10,13,'$'

s3 db 'Введите х3',10,13,'$'

x1 db ?

x2 db ?

yc db ? ;частное

yo db ? ;остаток

Code

start:

mov ax,@data

Mov ds,ax

 


mov ah,09h

mov dx, offset s1

int 21h ;вывод строки

mov ah,01h                               вводим х1

int 21h ;вводим число

sub al,30h             ;al:=x1

mov x1,al


mov ah,09h

mov dx, offset s2

int 21h

mov ah,01h                               вводим х2

int 21h

sub al,30h             ;al:=x2

mov x2,al

 

mov ah,09h

mov dx, offset s3

int 21h

mov ah,01h                               вводим х3

int 21h

sub al,30h             ;al:=x3

 


mov bl,x2      ;bl:=x2

sub bl,al       ;bl:=x2-x3

xchg al,bl       ;al:=bl, al:=x2-x3

xor ah,ah     ;ax:=x2-x3               вычисляем у

mov dl,x1      ;dl:=x1

div dl           ;ax/dl,    ax/x1

 

mov yc,ah

mov yo,al

 

; можно вывести результат на экран

 




Mov ax ,4 c 00 h

Int 21h

End start

Команды сдвига

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

Все команды сдвига устанавливают флаг переноса cf.

shl операнд,счетчик_сдвигов (Shift Logical Left) - логический сдвиг влево. Содержимое операнда сдвигается влево на количество битов, определяемое значением счетчик_сдвигов. Справа (в позицию младшего бита) вписываются нули;

shr операнд,счетчик_сдвигов — логический сдвиг вправо.

 

shl al, 2 Было al=00001101 Стало al=00110100   shr ax, 8 Было ax=4faf, стало ax=004f   mov cl,05h shl bh, cl bh=00010110 bh=11000000   shr  x1,3

Алгоритм работы команд:

· очередной “выдвигаемый” бит устанавливает флаг cf;

· бит, вводимый в операнд с другого конца, имеет значение 0;

· при сдвиге очередного бита он переходит во флаг cf, при этом значение предыдущего сдвинутого бита теряется!

sal операнд,счетчик_сдвигов (Shift Arithmetic Left)

sar операнд,счетчик_сдвигов

арифметический сдвиг влево/вправо. Содержимое операнда сдвигается влево/ вправо на количество битов, определяемое значением счетчик_сдвигов. Справа/ Слева в операнд вписываются нули.

Команда sal не сохраняет знака, но устанавливает флаг cf в случае смены знака очередным выдвигаемым битом. В остальном команда sal полностью аналогична команде shl;

Команда sar сохраняет знак, восстанавливая его после сдвига каждого очередного бита.

 

Команды циклического сдвига

rol операнд , счетчик _ сдвигов (Rotate Left) — циклический сдвиг влево.

Содержимое операнда сдвигается влево на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые влево биты записываются в тот же операнд справа.

ror операнд,счетчик_сдвигов (Rotate Right) — циклический сдвиг вправо.


rol al, 3 Было al=10101100 Стало al=01100101   ror ax, 8 Было ax=4faf, стало ax=af4f   mov cl,05h rol bh, cl bh=00010110 bh=11000010   ror x1,2

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

Команды циклического сдвига через флаг переноса cf отличаются от команд простого циклического сдвига тем, что сдвигаемый бит не сразу попадает в операнд с другого его конца, а записывается сначала в флаг переноса cf. Лишь следующее исполнение данной команды сдвига (при условии, что она выполняется в цикле) приводит к помещению выдвинутого ранее бита с другого конца операнда (см. рис. 4).

rcl операнд,счетчик_сдвигов (Rotate through Carry Left) — циклический сдвиг влево через перенос.

Содержимое операнда сдвигается влево на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса cf.

rcr операнд,счетчик_сдвигов (Rotate through Carry Right) — циклический сдвиг вправо через перенос.

Содержимое операнда сдвигается вправо на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса cf.

 

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

Под рассогласованием битовой последовательности здесь и далее подразумевается действие, которое позволяет некоторым образом локализовать и извлечь нужные участки этой последовательности и записать их в другое место

Пример. Дано отрицательное число. Выведите на экран его значение по модулю деленное на 2.

Любое отрицательное число хранится в дополнительном формате

-1 ffh

-2 feh

-10         f6h

получить значение числа по модулю, можно осуществив логическое отрицание над числом и добавив 1.

 


Model    small

Stack    100h

Data

x db -12

Code

start:

mov ax,@data

Mov ds,ax

 

mov al,x ;в al отрицательное число

not al

inc al  ;число по модулю

shr al,1

;выводим результат на экран

 

aam ;

;преобразование двоичного числа меньшего 63h (9910), которое находится в al в его ;неупакованный BCD-эквивалент

; -разделить значение регистра al на 10;

; -записать частное в регистр ah, остаток — в регистр al.

 

mov dx,ax ;число в регистр dx

or dx,3030h ;получаю ASCII код числа

xchg dh,dl ;меняю местами старший и младший байт, для вывода символа из dl

mov ah,02h   ;

int 21h ;вывожу старшую половинку числа

xchg dh,dl ;меняю местами старший и младший байт,

int 21h ;вывожу младшую половинку числа

 

Mov ax,4c00h

Int 21h

End start



Команды передачи управления

 

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

1. Команды безусловной передачи управления:

- команда безусловного перехода; jmp

- вызова процедуры и возврата из процедуры; call, ret

- вызова программных прерываний и возврата из программных прерываний. Int, iret

2. Команды условной передачи управления:

- команды перехода по результату команды сравнения cmp;

- команды перехода по состоянию определенного флага;

- команды перехода по содержимому регистра ecx/cx.

3. Команды управления циклом:

- команда организации цикла со счетчиком ecx/cx;

- команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

jmp адрес_перехода - безусловный переход без сохранения информации о точке возврата. Аналог goto.

jmp m1                                       m4:

…                                                …

m1:                                             jmp m4

 

Условные переходы

Команды условного перехода имеют одинаковый синтаксис:

jcc метка_перехода

Мнемокод всех команд начинается с “j” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой. Что касается операнда метка_перехода, то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается.

Для того чтобы принять решение о том, куда будет передано управление командой условного перехода, предварительно должно быть сформировано условие, на основании которого и будет приниматься решение о передаче управления. Источниками такого условия могут быть:

- любая команда, изменяющая состояние арифметических флагов;

- команда сравнения cmp, сравнивающая значения двух операндов;

- состояние регистра ecx/cx.

 

Условные переходы по содержимому флагов

Название флага Номер бита в eflags/flag Команда условного перехода Значение флага для осуществления перехода
Флаг переноса cf 1 jc cf = 1
Флаг четности pf 2 jp pf = 1
Флаг нуля zf 6 jz zf = 1
Флаг знака sf 7 js sf = 1
Флаг переполнения of 11 jo of = 1
Флаг переноса cf 1 jnc cf = 0
Флаг четности pf 2 jnp pf = 0
Флаг нуля zf 6 jnz zf = 0
Флаг знака sf 7 jns sf = 0
Флаг переполнения of 11 jno of = 0

jcxz метка_перехода (Jump if cx is Zero) — переход, если cx ноль;

jecxz метка_перехода (Jump Equal ecx Zero) — переход, если ecx ноль.

 

Пример программы: определите, равны ли два числа вводимые пользователем с клавиатуры.

Model    small

Stack    100h

Data

s1 db 'числа равны$'

s2 db 'числа не равны$'

.code

start:

mov ax,@data

mov ds,ax

mov ah,01h

int 21h ;ввели первое число

mov dl,al

mov ah,01h

int 21h ;ввели второе число

sub al,dl ;сравнили числа

jnz m1

mov dx, offset s1

jmp m2

m1: mov dx, offset s2

m2: mov ah,09h

int 21h ;выводим информационную строку

Mov ax ,4 c 00 h

Int 21h

End start

 

Команда сравнения cmp

cmp операнд_1,операнд_2 - сравнивает два операнда и по результатам сравнения устанавливает флаги. Команда сравнения cmp имеет интересный принцип работы. Он абсолютно такой же, как и у команды вычитания sub. Единственное, чего она не делает — это запись результата вычитания на место первого операнда.

Алгоритм работы:

-выполнить вычитание (операнд1-операнд2);

-в зависимости от результата установить флаги, операнд1 и операнд2 не изменять (то есть результат не запоминать).

 

Условные переходы после команд сравнения

Типы операндов Мнемокод команды условного перехода Критерий условного перехода Значения флагов для осществления перехода
Любые je операнд_1 = операнд_2 zf = 1
Любые jne операнд_1<>операнд_2 zf = 0
Со знаком jl/jnge операнд_1 < операнд_2 sf <> of
Со знаком jle/jng операнд_1 <= операнд_2 sf <> of or zf = 1
Со знаком jg/jnle операнд_1 > операнд_2 sf = of and zf = 0
Со знаком jge/jnl операнд_1 => операнд_2 sf = of
Без знака jb/jnae операнд_1 < операнд_2 cf = 1
Без знака jbe/jna операнд_1 <= операнд_2 cf = 1 or zf=1
Без знака ja/jnbe операнд_1 > операнд_2 cf = 0 and zf = 0
Без знака jae/jnb операнд_1 => операнд_2 cf = 0

 

Пример программы: определите, равны ли два числа вводимые пользователем с клавиатуры.

Model    small

Stack    100h

Data

s1 db 'числа равны$'

s2 db 'числа не равны$'

.code

start:

mov ax,@data

mov ds,ax

mov ah,01h

int 21h ;ввели первое число

mov dl,al

mov ah,01h

int 21h ;ввели второе число

cmp al,dl ;сравнили числа

jne m1

mov dx, offset s1

jmp m2

m1: mov dx, offset s2

m2: mov ah,09h

int 21h ;выводим информационную строку

Mov ax ,4 c 00 h

Int 21h

end start

 

Организация циклов

loop метка_перехода (Loop) — повторить цикл

Работа команды заключается в выполнении следующих действий:

- декремента регистра ecx/cx;

- сравнения регистра ecx/cx с нулем:

- если (ecx/cx) > 0, то управление передается на метку перехода;

- если (ecx/cx) = 0, то управление передается на следующую после loop команду

mov cx, количество циклов

м1: тело цикла

 loop m1

loope/loopz метка_перехода (Loop till cx <> 0 or Zero Flag = 0) — повторить цикл, пока cx <> 0 или zf = 0.

loopne/loopnz метка_перехода (Loop till cx <> 0 or Not Zero flag=0) — повторить цикл пока cx <> 0 или zf = 1

Недостаток команд организации цикла loop, loope/loopz и loopne/loopnz в том, что они реализуют только короткие переходы (от –128 до +127 байт).


Организация вложенных циклов

mov cх,n ; в сх заносим количество итераций внешнего цикла

m1:

push cx

mov cx,n1; в сх заносим количество итераций внутреннего цикла

                       m2:

тело внутреннего цикла

                       loop m2

    …

    pop cx

 loop m1

 

Пример программы: Напишите программу подсчета у=1+2+3+…+n, n не более 10000.

 

model    small

.stack 100h

.data

yb dd ?

ym dw ?

s1 db 'введите n',10,13,'$'

.code

start:

mov ax,@data

mov ds,ax

 

mov dx, offset s1

mov ah,09h

int 21h


mov cx,3

m: shl bx,4

mov ah,01h

int 21h            вводим n в регистр bx

 sub ax,130h

add bx,ax

loop m

 

mov cx,bx

xor dx,dx

xor al,al

m1: add dx,cx     считаем у

jnc m2

mov al,1

m2: loop m1

 

cmp al,1

je  m3

mov ym,dx

m3: mov yb,edx

 

mov ax,4c00h

int 21h

end start


Цепочечные команды

(Команды обработки строк символов)

Цепочка – это последовательность элементов, размер которых может быть байт, слово, двойное слово. Содержимое этих элементов может быть любое – символы, числа.

В системе команд микропроцессора имеется семь операций-примитивов обработки цепочек.

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

Вместе с цепочечными командами обычно применяют префиксы повторений, которые ставятся перед командой в поле [метки]. Цепочечная команда без префикса выполняется один раз. С префиксом цепочечные команды выполняются циклично.

rep (REPeat) - команда выполняется, пока содержимое в ecx/cx не станет равным 0. При этом цепочечная команда, перед которой стоит префикс, автоматически уменьшает содержимое ecx/cx на единицу. Та же команда, но без префикса, этого не делает.

repe или repz (REPeat while Equal or Zero) - команда выполняется до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен 1. Как только одно из этих условий нарушается, управление передается следующей команде программы

repne или repnz (REPeat while Not Equal or Zero) - команда циклически выполняется до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен нулю. При невыполнении одного из этих условий работа команды прекращается.

Формирования физического адреса операндов адрес_источника и адрес_приемника происходит следующим образом:

адрес_источника — пара ds:esi/si;

адрес_приемника — пара es:edi/di

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

- от начала цепочки к ее концу, то есть в направлении возрастания адресов;

- от конца цепочки к началу, то есть в направлении убывания адресов.

Цепочечные команды сами выполняют модификацию регистров, адресующих операнды, обеспечивая тем самым автоматическое продвижение по цепочке. Количество байт, на которые эта модификация осуществляется, определяется кодом команды. А вот знак этой модификации определяется значением флага направления df (Direction Flag) в регистре eflags/flags. Состоянием флага df можно управлять с помощью двух команд, не имеющих операндов:

cld (Clear Direction Flag) — очистить флаг направления df = 0, значение индексных регистров esi/si и edi/di будет автоматически увеличиваться (операция инкремента) цепочечными командами, то есть обработка будет осуществляться в направлении возрастания адресов;

std (Set Direction Flag) — установить флаг направления df = 1, то значение индексных регистров esi/si и edi/di будет автоматически уменьшаться (операция декремента) цепочечными командами, то есть обработка будет идти в направлении убывания адресов.

Типовой набор действий для выполнения любой цепочечной команды:

- Установить значение флага df в зависимости от того, в каком направлении будут обрабатываться элементы цепочки — в направлении возрастания или убывания адресов.

- Загрузить указатели на адреса цепочек в памяти в пары регистров ds:(e)si и es: (e)di.

- Загрузить в регистр ecx/cx количество элементов, подлежащих обработке.

- Выдать цепочечную команду с префиксом повторений.

Пересылка цепочек

movs адрес_прием, адрес_источника (MOVe String)- переслать цепочку;

movsb MOVe String Byte) — переслать цепочку байт;

movsw (MOVe String Word) — переслать цепочку слов;

movsd (MOVe String Double word) — переслать цепочку двойных слов.

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

Для цепочечных команд с операндами типа movs адрес_приемника,адрес_источника, не существует машинного аналога. При трансляции в зависимости от типа операндов транслятор преобразует ее в одну из трех машинных команд: movsb, movsw или movsd.

Сама по себе команда movs пересылает только один элемент, исходя из его типа, и модифицирует значения регистров esi/si и edi/di. Если перед командой написать префикс rep, то одной командой можно переслать до 64 Кбайт данных. Число пересылаемых элементов должно быть загружено в счетчик — регистр cx (use16) или ecx (use32).

Пример проги. Пересылка строк командой movs

MODEL small

STACK 256

.data

source db 'Тестируемая строка','$' ;строка-источник

dest db 19 DUP (' ') ;строка-приёмник

.code

main:

 mov ax,@data         ;загрузка сегментных регистров

 mov ds,ax      ;настройка регистров DS и ES на адрес сегмента данных

 mov es,ax

 cld                  ;сброс флага DF — обработка строки от начала к концу

 lea si,source            ;загрузка в si смещения строки-источника

 lea di,dest      ;загрузка в DS смещения строки-приёмника

 mov cx,20      ;для префикса rep — счетчик повторений (длина строки)

rep movs dest,source ;пересылка строки

 lea dx,dest

 mov ah,09h ;вывод на экран строки-приёмника

 int 21h

 mov ax,4c00h

 int 21h

end main




Операция сравнения цепочек

cmps адрес_приемника,адрес_источника(CoMPare String) — сравнить строки;

cmpsb (CoMPare String Byte) — сравнить строку байт;

cmpsw (CoMPare String Word) — сравнить строку слов;

cmpsd (CoMPare String Double word) — сравнить строку двойных слов.

Алгоритм работы команды cmps заключается в последовательном выполнении вычитания (элемент цепочки-источника — элемент цепочки-получателя) над очередными элементами обеих цепочек. Принцип выполнения вычитания командой cmps аналогичен команде сравнения cmp. Она, так же, как и cmp, производит вычитание элементов, не записывая при этом результата, и устанавливает флаги zf, sf и of.

После выполнения вычитания очередных элементов цепочек командой cmps, индексные регистры esi/si и edi/di автоматически изменяются в соответствии со значением флага df на значение, равное размеру элемента сравниваемых цепочек.

Чтобы заставить команду cmps выполняться несколько раз, то есть производить последовательное сравнение элементов цепочек, необходимо перед командой cmps определить префикс повторения. С командой cmps можно использовать префикс повторения repe/repz или repne/repnz:

- repe или repz — если необходимо организовать сравнение до тех пор, пока не будет выполнено одно из двух условий: достигнут конец цепочки (содержимое ecx/cx равно нулю) или в цепочках встретились разные элементы (флаг zf стал равен нулю);

- repne или repnz — если нужно проводить сравнение до тех пор, пока: не будет достигнут конец цепочки (содержимое ecx/cx равно нулю) или в цепочках встретились одинаковые элементы (флаг zf стал равен единице).

Пример программы Сравнение двух строк командой cmps

MODEL small

STACK 256

.data

sov db 0ah,0dh,'Строки совпадают.','$'

nesov db 0ah,0dh,'Строки не совпадают','$'

s1 db '0123456789',0ah,0dh,'$';исследуемые строки

s2 db 10

s3 db 11 dup (0)

.code

main:

 mov ax,@data ;загрузка сегментных регистров

 mov ds,ax

 mov es,ax ;настройка ES на DS

;вводим строку

mov ah, 0аh

mov dx, offset s2

int 21h

;поиск совпадающих элементов, сброс флага DF - сравнение в направлении возрастания адресов

cld

lea si,s1 ;загрузка в si смещения string1

lea di,s3 ;загрузка в di смещения string2

mov cx,10 ;длина строки для префикса repe

repe cmpsb     ;сравнение строк (пока сравниваемые элементы строк равны)

;выход при обнаружении не совпавшего элемента

jcxz equal        ;cx=0, то есть строки совпадают

lea dx, nesov

jmp exit ;выход

equal:    lea dx, sov

exit: mov ah,09h

int 21h ;вывод сообщения

mov ax,4c00h

int 21h

end main ;конец программы

Операция сканирования цепочек

scas адрес_приемника (SCAning String) — сканировать цепочку;

scasb (SCAning String Byte) — сканировать цепочку байт;

scasw (SCAning String Word) — сканировать цепочку слов;

scasd (SCAning String Double Word) — сканировать цепочку двойных слов

Эти команды осуществляют поиск искомого значения, которое находится в регистре al/ax/eax. Принцип поиска тот же, что и в команде сравнения cmps, то есть последовательное выполнение вычитания

(содержимое регистра_аккумулятора – содержимое очередного_элемента_цепочки).

В зависимости от результатов вычитания производится установка флагов, при этом сами операнды не изменяются.

Так же, как и в случае команды cmps, с командой scas удобно использовать префиксы repe/repz или repne/repnz:

- repe или repz — если нужно организовать поиск до тех пор, пока не будет выполнено одно из двух условий: достигнут конец цепочки (содержимое ecx/cx равно 0) или в цепочке встретился элемент, отличный от элемента в регистре al/ax/eax;

- repne или repnz — если нужно организовать поиск до тех пор, пока не будет выполнено одно из двух условий достигнут конец цепочки (содержимое ecx/cx равно 0)или в цепочке встретился элемент, совпадающий с элементом в регистре al/ax/eax.

Пример проги. найти количество * в строке

MODEL small

STACK 256

.data

s1 db 20

s2 db 21 dup ?

s3 db 'количество * в строке',0ah,0dh,'$'

.code

main:

 mov ax,@data

 mov ds,ax

 mov es,ax ;настройка ES на DS

;вводим строку

mov ah,0ah

mov dx, offset s1

int 21h

;поиск *

mov al,'*' ;символ для поиска — `а`(кириллица)

cld ;сброс флага df

lea di, s2 ;загрузка в es:di смещения строки

inc di ;первый элемент в s3 это количество введенных символов, его игнорируем

xor bl ;обнуляем счетчик звездочек

mov cx,20 ;для префикса repne — длина строки

m1: repne scasb     ;пока искомый символ и символ в строке не совпадут идет поиск, ;выход при совпадении

je found ;если равны - переход на обработку

;вывод количества звездочек в строке

 mov ah,09h

 mov dx,offset s3

 int 21h ;вывод сообщения nochar

mov al,bl

aam

or ax, 3030h

mov dx,ax

xchg dh,dl

mov ah, 02h

int 21h

xchg dh,dl

int 21h

 mov ax,4c00h

 int 21h

;суммируем количество звездочек

found:    inc bl

jmp m1

 end main

Дата: 2019-12-22, просмотров: 221.