Во-первых, ни к чему устанавливать флаг нуля ZF командой or cx,cx, ведь есть команда jcxz, которая, не изменяя флагов, проверяет содержимое регистра cx на равенство нулю и производит переход по указанному адресу, если cx=0.
То есть вместо
repne scasb
or cx,cx; или test cx,cx
je ex
можно написать
repne scasb
jcxz ex
Во-вторых, команда repne scasb сама по себе устанавливает флаг ZF в зависимости от того, по какой причине произошёл выход из этого микроцикла. Если ZF установлен, то найден искомый байт, если сброшен, то cx = 0.
repne scasb
jne ex
В-третьих, если искомый байт находится на последней позиции, то конструкции
repne scasb
or cx,cx
je ex
и
repne scasb
jcxz ex
его не посчитают.
Программа (TASM, процессор i8086 и старше, реальный режим, 16-разрядное приложение MS DOS):
.model small
.stack 100h
.code
N78220854:
mov ax,@data
mov ds,ax
mov es,ax
mov ah,9
lea dx,Prompt1
int 21h
inc ah
lea dx,Buffer
int 21h
dec ah
lea dx,Prompt2
int 21h
mov ah,1
int 21h
mov cl,LenStr
xor ch,ch
mov bl,ch
lea di,String
FindLoop:
repne scasb
jne Output
inc bl
jmp FindLoop
Output:
mov al,bl
mov bh,10
Prepare:
xor ah,ah
div bh
add ah,30h
push ax
inc cx
or al,al
jnz Prepare
mov ah,9
lea dx,Result
int 21h
mov ah,2
Print:
pop dx
mov dl,dh
int 21h
loop Print
lea dx,ResUnit
mov ah,9
int 21h
mov ah,8
int 21h
mov ah,4Ch
int 21h
.data
MaxLen equ 79
Prompt1 db 'Введите строку: ',13,10,36
Prompt2 db 13,10,'Введите искомый символ: ',36
Result db 13,10,'Заданный символ встречается в строке $'
ResUnit db ' раз. $'
Buffer db MaxLen + 1
LenStr db ?
String db MaxLen + 1 dup (?)
end N78220854
