Учебный курс. Часть 17. Команды LOOPZ и LOOPNZ
Автор: xrnd | Рубрика: Учебный курс | 05-05-2010 |
Распечатать запись
Кроме команды LOOP и команд условных переходов существуют ещё две команды, позволяющие организовывать циклы. Это команды LOOPZ (или её синоним LOOPE) и LOOPNZ (синоним — LOOPNE). Действие этих команд очень напоминает LOOP, за исключением того, что дополнительно анализируется флаг нуля ZF.
Переход к метке цикла осуществляется в том случае, если после декремента содержимое CX не равно 0 и выполняется условие: ZF=1 (для команды LOOPZ/LOOPE) или ZF=0 (LOOPNZ/LOOPNE).
Эти команды удобно использовать в алгоритмах, где цикл должен завершаться в двух случаях:
- выполнено требуемое количество итераций;
- выполнено некоторое условие досрочного завершения цикла.
Простейший пример такого алгоритма — поиск числа или символа в массиве. Поиск завершается, если один из элементов массива совпал с искомым или если достигнут конец массива. В качестве примера рассмотрим программу для поиска символов в строке. Пользователь вводит символ, а программа определяет, содержится такой символ в строке или нет. Для выхода из программы нужно нажать ENTER.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Безусловный переход на метку start ;-- Данные ------------------------------------------------------------ string db 'Hello!',13,10,'$' length db 6 s_entchar db 'Enter char (Press ENTER to exit):$' s_found db ' - found!',13,10,'$' s_nfound db ' - not found!',13,10,'$' ;---------------------------------------------------------------------- start: mov ah,09h ;\ mov dx,string ; > Вывод строки int 21h ;/ main: mov dx,s_entchar ;\ int 21h ;/ Вывод приглашения для ввода символа mov ah,01h ;\ int 21h ;/ Ввод символа cmp al,0Dh ;Нажата клавиша ENTER? je exit ;Если да, то переход на метку exit mov bx,string-1 ;BX = (адрес строки - 1) movzx cx,[length] ;CX = длина строки search: inc bx ;Инкремент BX cmp al,[bx] ;Сравнение введённого символа с символом строки loopne search ;Цикл, если не равно. je found ;Если равно, то символ найден. mov dx,s_nfound ;DX = адрес строки ' - not found!' print_result: mov ah,09h ;\ int 21h ;/ Вывод результата поиска jmp main ;Безусловный переход на метку main found: mov dx,s_found ;DX = адрес строки ' - found!' jmp print_result ;Безусловный переход на метку print_result exit: mov ax,4C00h ;\ int 21h ;/ Завершение программы |
Обратите внимание, изначально в BX загружается значение (адрес строки — 1), так как цикл начинается с команды инкремента. Результат работы программы:
Упражнение
Объявите в программе два массива слов. Размер массивов должен быть одинаков и храниться в 8-битной переменной без знака. Напишите программу сравнения двух массивов, используя команду LOOPZ. (Массивы равны, если все их элементы соответственно равны. Цикл можно завершить, если найдена хотя бы одна пара не совпадающих элементов). Выведите на экран строку, сообщающую о результате сравнения. Сами массивы печатать не нужно. Свои программы можете выкладывать в комментариях.
14-05-2010 16:24
use16
org 100h
jmp start
;————————
array1 dw 2123,1456,2000,2222,1111
array2 dw 2123,1456,2000,2222,1111
length db 5
ravno db ‘massivbl ravnbl$’
neravno db ‘massivbl ne ravnbl$’
;————————
start:
movzx cx,[length]
sub si,si
loop1:
mov ax,word[array1+si]
mov bx,word[array2+si]
add si,2
cmp ax,bx
loopz loop1
jz ravno1
mov ah,09h
mov dx,neravno
int 21h
jmp exit
ravno1:
mov ah,09h
mov dx,ravno
int 21h
exit:
mov ah,08h
int 21h
mov ax,4C00h
int 21h
14-05-2010 20:00
Замечательно, всё правильно.
12-12-2010 12:36
Задание понял немного неправильно — слова…слова, но интересно было посмотреть размерность строкового массива. И как можно поставить в строку знак «≠»?
use16
org 100h
jmp start
array1 db ‘топот$’,’шорох$’,’поп$’,’горох$’
array2 db ‘топот$’,’поп$’,’шорох$’,’горох$’
rm db 22
vivod1 db ‘array1 = array2$’
vivod2 db ‘array1 array2$’
pak db 13,10,’Press any key…$’
start:
xor ax,ax
movzx cx,[rm]
mov si,-1
prov: inc si
mov al,[array1+si]
cmp al,[array2+si]
loopz prov
jz v1
mov dx, vivod2
jmp vivod
v1: mov dx, vivod1 ; Так чуть меньше кода, чем в предыдущем примере
vivod : mov ah,09h
int 21h
exit:
mov ah,09h
mov dx,pak
int 21h
mov ah,08h
int 21h
mov ax,4C00h
int 21h
12-12-2010 22:40
Массив слов порадовал 🙂
Программа написана правильно.
Знака «≠» нет в консольном шрифте, его в строку не добавить.
15-01-2011 20:51
use16 ;Ãåíåðèðîâàòü 16-áèòíûé êîä
org 100h ;Ïðîãðàììà íà÷èíàåòñÿ ñ àäðåñà 100h
jmp start ;Áåçóñëîâíûé ïåðåõîä íà ìåòêó start
;— Äàííûå ————————————————————
array1 db ‘l$’,’o$’,’o$’,’p$’
array2 db ‘l$’,’o$’,’o$’,’p$’
length db 5
press db ‘ne pavn $’
press1 db ‘ pavn $’
;———————————————————————-
start:
movzx cx,[length]
mov si,1
mov ah,09h
E:
mov dl,byte[array1+si+1]; +1 чтобы убрать $’
mov dh,byte[array2+si+1]
cmp dl,dh ;если результат =0 , значит равны
Jnz E1 ; если результат не ноль переход по метке
inc si ; si +1 , z =0
mov di,cx
sub di,di ; z=1
loopz E
mov dx,press1
int 21h
jmp exit
E1:
mov dx,press
int 21h
exit:
mov ah,08h
int 21h
mov ax,4C00h
int 21h
18-01-2011 21:40
Слова без знака — это 16-битные целые, а вовсе не те слова, которыми люди разговаривают :)))))
А это какой-то хитрый хак:
Я имел в виду совсем другое. Вместо этих трех команд можно просто использовать команду LOOP. Смысл этого упражнения в том, чтобы проверять флаг ZF командой LOOPZ. А переход сделать после команды цикла. Если ZF=1 массивы равны, иначе — массивы не равны.
18-01-2011 22:32
На самом дели всё дела в
inc si , эта команда меняет флаг , поэтому я не как немок понять , как сделать так чтобы , +1 , но флаг не трогать , нечего лутьще придумать сам не смог )
На самом дели я понял принцы , но не понял как его реализовать , ну потом подсматрел как другие это сделали ,)
И понял cmp тоже меняет флаг , не тралезуя эффект inc si
В конечнам итоге я хотел вот это ,)
E:
mov dl,byte[array1+si+1];
mov dh,byte[array2+si+1];
inc si
cmp dl,dh
loopz E
Jz E1 ; неравны
mov dx,press1 ; равны
19-01-2011 18:33
Ага. Только неравны и равны надо местами поменять.
Либо делать переход командой
15-02-2011 21:57
use16
org 100h
jmp start
a1 db 0, 2, -5
a2 db 0, 2, -5
number db 3
result_yes db ‘Arrays are equal’, 0Dh, 0Ah, ‘$’
result_no db ‘Arrays are not equal’, 0Dh, 0Ah, ‘$’
start:
mov bx, a1-1
mov si, a2-1
movzx cx, [number]
jmp compare
compare:
inc bx
inc si
mov al, [bx]
cmp al, [si]
loope compare
jne no
mov dx, result_yes
jmp print_result
no:
mov dx, result_no
print_result:
mov ah, 09h
int 21h
mov ah, 08h
int 21h
mov ax, 4C00h
int 21h
18-02-2011 13:11
В общем всё правильно, но массивы состоят из байтов, а не из слов.
И есть одна лишняя команда:
31-03-2011 01:09
use16
org 100h
jmp start
;—————
arr1 dw 1234, 4033, 5645
arr2 dw 1234, 4033, 5645
count db 3
s_equal db 10,13,’equal!’,10,13,’$’
s_nequal db 10,13,’not equal!’,10,13,’$’
;————————
start:
movzx cx,[count]
xor si,si
compar:
mov ax,word[arr1+si]
mov bx,word[arr2+si]
add si,2
cmp ax,bx
loopz compar
jz equal
mov dx,s_nequal
jmp output
equal:
mov dx,s_equal
output:
mov ah,09h
int 21h
mov ah,08h
int 21h
mov ax,4C00h
int 21h
01-04-2011 15:51
Здесь тоже всё правильно 🙂
13-03-2012 18:38
use16
org 100h
jmp start
x db 5
y db 7
array1 dw 10,20,35,40,50
array2 dw 10,20,30,40,50
length db 5
equal db 13,10, ‘Equal$’
nequal db 13,10, ‘Not equal$’
press db 13,10,’Press any key…$’
start:
movzx cx,[length]
xor si,si
mov bx,array1-2
che:
mov ax,[array2+si]
add bx,2
add si,2
cmp ax,[bx]
loopz che
jne nee
mov ah,09h
mov dx,equal
int 21h
jmp exit
nee:
mov ah,09h
mov dx,nequal
int 21h
exit:
mov ah,09h
mov dx,press
int 21h
mov ah,08h
int 21h
mov ax,4c00h
int 21h
13-03-2012 18:40
Я вот попробовал конструкцию
cmp [ax],[bx] и
cmp [array1],[array2]
так компилятор ругается….
Потом вычитал, что оба операнда не могут быть ячейками памяти, только один…..
может я ошибаюсь…..
14-03-2012 07:47
Оба операнда не могут быть ячейками памяти
10-08-2012 21:45
извините пока нашел сайт, пока дошел до 17-го упражнения уже и опоздал, но надеюсь вы подскажете мне где-же тут ошибка.
USE16
ORG 100H
JMP START
N DB 5
ARRAY1 DB 1,1,1,1,1
ARRAY2 DB 1,1,1,1,1
STRING0 DB 10,13,’=$’
STRING1 DB 10,13,’!=$’
STRING2 DB ‘Press Enter to run programm$’,10,13
STRING3 DB 10,13,’Press Esc to exit$’
START:
MOV AH,09H
MOV DX,STRING2
INT 21H
MOV AH,09H
MOV DX,STRING3
INT 21H
MOV AH,01H
INT 21H
CMP AL,01B
JE EXIT
CMP AL,0DH
JE LOOP2
EXIT:
MOV AH,08H
INT 21H
MOV AX,4C00H
INT 21H
EXIT1:
MOV AH,09H
MOV DX,STRING1
INT 21H
JMP EXIT
LOOP2:
MOV BX,ARRAY1
MOV DX,ARRAY2
MOVZX CX,[N]
COMPARE:
INC BX
INC DX
CMP BX,DX
LOOPNZ COMPARE
JNE EXIT1
MOV AH,09H
MOV DX,STRING0
INT 21H
06-02-2014 18:21
Как-то так. Работает.
USE16
ORG 100H
JMP START
;————————
N DB 5
ARRAY1 dw 1,1,1,1,1
ARRAY2 dw 1,1,1,1,1
STRING0 DB 10,13,’=$’
STRING1 DB 10,13,’!=$’
STRING2 DB ‘Press Enter to run programm$’,10,13
STRING3 DB 10,13,’Press Esc to exit$’
;————————
START:
sub si,si
MOVZX CX,[N]
MOV AH,09H
MOV DX,STRING2
INT 21H
MOV AH,09H
MOV DX,STRING3
INT 21H
MOV AH,01H
INT 21H
CMP AL,01B
JE EXIT
CMP AL,0DH
JE COMPARE
EXIT:
MOV AH,08H
INT 21H
MOV AX,4C00H
INT 21H
EXIT1:
MOV AH,09H
MOV DX,STRING0
INT 21H
JMP EXIT
COMPARE:
MOV AX,word[ARRAY1+si]
MOV BX,word[ARRAY2+si]
add si,2
CMP AX,BX
LOOPZ COMPARE
jz EXIT1
mov ah,09h
mov dx,STRING1
int 21h
jmp EXIT
05-11-2016 21:15
se16; вывод на консоль каждого сравнения. в столбик
org 100h
mov ah,09h
movzx cx,[length]
mov bx,str1-2
mov si,str2-2
lp2:
add bx,2
add si,2
mov al,[bx]
cmp al,[si]
loope lp1
jg more
jl less
lp1:
mov dx,A
int 21h
cmp cx,0h
je exit
jmp lp2
more:
mov dx,B
int 21h
cmp cx,0h
je exit
jmp lp2
less:
mov dx,C
int 21h
cmp cx,0h
je exit
jmp lp2
exit:
mov ah,08h
int 21h
mov ax, 4C00h
int 21h
;________________________________
str1 dw 111,222,333,454,555,666,777,888,999,1001
str2 dw 101,222,333,444,555,666,777,888,999,1000
length db 10
A db 13,10,’a=b$’
B db 13,10,’a>b$’
C db 13,10,’a<b$'
06-11-2016 23:15
Можно немного оптимизировать
«jcxz метка» (переход при CX=0)? заместо:
«cmp cx,0h
je метка»
18-03-2017 13:04
Почему не работает (При нажатие Enter, виснет dos-box):
use16
org 100h
jmp start
string db ‘Hello!’, 13, 10, ‘$’
length db 6
ask db 13, 10, ‘Enter a char (ENTER to exit) : $’
f db ‘The same character is exists!$’
nf db ‘The same character is not exists!$’
start:
mov ah, 09h
mov dx, string
int 21h
main:
mov ah, 09h
mov dx, ask
int 21h
mov ah, 01h
int 21h
cmp al, 0Dh
je exit
jmp main
exit:
mov ax, 4c00h
int 21
21-08-2019 18:30
use16
org 100h
start:
xor cx,cx
mov cl,[n]
lp1:
mov si,cx
mov ax,[arr1+si]
cmp ax,[arr2+si]
loopz lp1
cmp cl,0
je ident
mov dx,bad
jmp exit
ident:
mov dx,good
exit:
mov ah,09h
int 21h
mov ax,4c00h
int 21h
arr1 dw 0000h,1111h,2222h,3333h,4444h,5555h
arr2 dw 0000h,1111h,2229h,3333h,4444h,5555h
n db 6
good db ‘Arrays match’,0ah,0dh,’$’
bad db ‘Mismatch found’,0ah,0dh,’$’
22-08-2019 09:13
Потом заметил — не хватает двух строк перед и после метки lp1:
. . .
xor cx,cx
mov cl,[n]
mov si,cx
shl si,1
lp1:
sub si,2
mov ax,[arr1 . . .
22-08-2019 10:00
А вот это, по идее, должно проверять массивы до конца и писать, в каких парах несовпадения (не более 9 элементов в массиве):
use16
org 100h
start:
xor bx,bx
xor di,di
mov dl,[n]
mov si,-2
try:
add si,2
mov ax,si
shr ax,1
cmp al,dl
je p_endl
mov ax,[arr1+si]
cmp ax,[arr2+si]
je try
mov dh,1 ; индикатор несовпадений
mov bx,2ch
add bx,di
mov ax,di
cmp ax,0
jz cont
p_2c20: ; запихнуть ‘, ‘ в str2
mov ax,202ch
mov word [str2+bx],ax
add di,2
add bx,2
cont: ; запихнуть номер пары в str2
mov ax,si
shr ax,1
add ax,31h ; смещение к цифрам в таблице символов
inc di
mov word [str2+bx],ax
jmp try
p_endl: ; запихнуть ‘.\n$’ в str2
inc bx
mov ax,0a2eh
mov word [str2+bx],ax
add bx,2
mov ax,240dh
mov word [srt2+bx],ax
print: ; вывести результат
test dh,1
jnz bad
mov dx,str1
jmp exit
bad:
mov dx,str2
exit:
mov ah,09h
int 21h
mov ax,4c00h
int 21h
arr1 dw 0000h,1111h,2222h,3333h,4444h,5555h,6666h,7777h,8888h,9999h
arr2 dw 0000h,1111h,2229h,3333h,4444h,5555h,6666h,7777h,8888h,9999h
n db 9
str1 db ‘The arrays do match’,0ah,0dh,’$’
str2 db ‘The arrays do not match. Mismatch found in: ‘,?