


Помогите пожалуйста, не получается с языком ассемблера. Не знаю что делать
Дана последовательность битов. Необходимо определить минимальную и максимальную длину подпоследовательностей, состоящих из битов 0.
Входные данные:
Массив байтов (BYTE), который следует рассматривать как последовательность битов
Значение типа WORD (общее количество битов в последовательности)
Выходные данные:
минимальная длина подпоследовательности из нулей
максимальная длина подпоследовательности из нулей
(если таких подпоследовательностей нет, вернуть -1)
Входное значение определяет точную длину последовательности в битах. Это означает, что последний байт массива может быть использован не полностью. Биты в каждом байте необходимо анализировать от младшего разряда к старшему (от младшего к старшему биту, то есть от правого к левому, если смотреть на байт).
вот что получилось:
XOR ESI, ESI ; индекс текущего бита
XOR EDI, EDI ; счетчик длины
MOV BX, [len] ; загружаю общую длину в BX
MOV [minLung], BX ; инициализирую minLung максимальной возможной длиной
MOV ECX, -1 ; загружаю -1 в ECX для инициализации maxLung
MOV [maxLung], CX ; инициализирую maxLung значением -1
ciclo:
CMP SI, [len] ; сравниваю индекс бита с длиной
JGE fine ; если индекс превысил длину, перейти к fine
MOV EAX, ESI ; загружаю текущий индекс в EAX
MOV EDX, EAX ; загружаю текущий индекс в EDX
AND EDX, 7 ; позиция бита (0...7)
SHR EAX, 3 ; номер байта, содержащего бит
MOV AL, [vet + EAX] ; загружаю текущий байт
MOV CL, DL ; CL содержит индекс текущего бита (0-7)
SHR AL, CL ; сдвигаю текущий байт вправо
AND AL, 1 ; выделяю текущий бит
CMP AL, 0 ; проверяю, равен ли бит 0
JNE aggiorna ; если бит равен 1, перейти к aggiorna
INC EDI ; увеличиваю длину подпоследовательности нулей
INC ESI ; перехожу к следующему биту
JMP ciclo ; продолжаю цикл
aggiorna:
CMP EDI, 0 ; проверяю, равна ли длина подпоследовательности нулей нулю
JE dopoaggiorna ; если да, прыгаю к dopoaggiorna
MOV AX, [minLung] ; загружаю текущую минимальную длину в AX
CMP EDI, EAX ; сравниваю текущую длину с минимальной
JGE saltamin ; если текущая длина больше или равна минимальной, прыгаю к saltamin
MOV [minLung], DI ; обновляю минимальную длину текущей
saltamin:
MOV AX, [maxLung] ; загружаю текущую максимальную длину в AX
CMP EDI, EAX ; сравниваю текущую длину с максимальной
JLE saltamax ; если текущая длина меньше или равна максимальной, прыгаю к saltamax
MOV [maxLung], DI ; обновляю максимальную длину текущей
saltamax:
XOR EDI, EDI ; обнуляю счетчик, начинаю заново
dopoaggiorna:
INC ESI ; перехожу к следующему биту
JMP ciclo ; продолжаю цикл
fine:
CMP EDI, 0 ; проверяю, равна ли длина подпоследовательности нулей нулю
JE controlla ; если да, переходим к controlla
MOV AX, [minLung] ; загружаю текущую минимальную длину в AX
CMP DI, AX ; сравниваю текущую длину с минимальной
JGE skipmin ; если текущая длина больше или равна минимальной, прыгаю к skipmin
MOV [minLung], DI ; обновляю минимальную длину текущей
skipmin:
MOV AX, [maxLung] ; загружаю текущую максимальную длину в AX
CMP DI, AX ; сравниваю текущую длину с максимальной
JLE skipmax ; если текущая длина меньше или равна максимальной, прыгаю к skipmax
MOV [maxLung], DI ; обновляю максимальную длину текущей
skipmax:
controlla:
MOV AX, [maxLung] ; загружаю текущую максимальную длину в AX
CMP AX, -1 ; сравниваю максимальную длину с -1
JNE fineasm ; если они не равны, прыгаю к fineasm
MOV AX, -1 ; если равны, устанавливаю минимальную длину в -1
слишком сложно. берём последовательность и сдвигаем её побитно, через перенос. если в переносе ноль, увеличиваем счётчик, если единица, запоминаем его и начинаем заполнять новый.
Когда последовательность кончится, останется отсортировать счётчики.
Наверное поздно ,но держи.
прошелся gdb дебаггером, вроде все работает
Но жизнь не буду ставить на эту программу
!
Но вообще конечно неудивительно что не получается
Я с дебаггером кое-как нашел 4 опечатки и 3 ошибки
В условии не говорится об отсутствии памяти, но я все сделал в регистрах
Со стековым фреймом было бы полегче
!
!
global _start
!
section .data
vet db 0xBC,0xFF,0x01
len dw 18
minLung db -1 ;МИНИМУМ нулей
maxLung db -1 ;МАКС нулей
!
section .text
;подпрограммы
jmp short _start
change_min_max:;use ebx
test edx,edx ; что если 2 1 подряд и у нас 0 в edx
jz immediate_return
!
movzx bx,byte[minLung]
cmp bl,-1 ;если нет то нет
CMOVZ bx,dx
cmp dx,bx
CMOVL bx,dx
mov byte[minLung],bl
!
movzx bx,byte[maxLung]
cmp bl,-1
CMOVZ bx,dx
cmp dx,bx
CMOVG bx,dx
mov byte[maxLung],bl
!
xor edx,edx
immediate_return:
ret
linux_end_process:
mov eax,1
xor ebx,ebx
int 80h
!
_start: mov byte[minLung],-1 ;подготовка к подготовке к программе
mov byte[maxLung],-1
mov cx,word[len]
!
test cx,cx
jz near end_absolute; вдруг длинна = 0
;В начале проверим есть ли 0 в последовательности
xor eax,eax
xor edx,edx
xor ebx,ebx
!
mov dx,cx ;cx=[len],len еще пригодится
mov esi,vet
cld ;поставили DIRECTION FLAG для ESI и LODSB
shr cx,3
jz contnue ;потому что что если у нас меньше 1 байта
;loop0 повторится 2^32 раза
loop0: lodsb
xor al,0xFF;
add ebx,eax ;если все 1 то щас ebx=0
loop loop0
test ebx,ebx
jnz READY ;если не 0 то 0 есть,можно анализировать
and dx,7
jz end_absolute ;если нет нулей и нет доп битов то это выполнится
contnue:xor eax,eax
;проверям 0 в доп битах
mov al,byte[esi];если нет доп битов то это не произойдет
;ну потому что после lodsb esi указывает на след элемент
mov cl,8 ;на нужно выделить эти доп биты
sub cl,dl ;для этого мы найдем сколько им не хватает до низшего бита
mov dl,0xFF; допстим у нас 2 доп бита. Нужно на 8-2 shft right
shr dl,cl ;что мы и делаем
shr al,cl
xor al,dl ;если они 1 то ebx = 0
add bl,al
test bl,bl
jnz READY
!
xor edx,edx ;потому что в конце там вызов
jmp end_absolute
;Ну чтож, 0 точно где-то есть
;НАчинаем программу
;DF=0;ESI,EAX=LODSB=vet
;EDX-кол-во 0
;ESI,EDX,EAX-USED
;EDI,EBP-free
READY: cld
xor eax,eax
xor edx,edx
xor ebx,ebx
mov esi,vet
movzx ecx,word[len]
mov edi,ecx ;Это нам еще понадобится
shr ecx,3
jz A_bits
;анализ битов на 0
loop1: lodsb
mov ah,8
loop1_1:shr al,1
jnc If_0;если бит - 0 то добавляем к счетчику 0+1
!
if_not0:call change_min_max
jmp after
!
If_0: add edx,1
!
after: sub ah,1
jnz loop1_1
sub ecx,1
jnz loop1
;Остался последний байт и с этим покончено
A_bits: movzx eax,byte[esi] ;edx-колво 0
mov ecx,8
and edi,7
sub ecx,edi
shr al,cl
sub cl,8
not cl
add cl,1
!
loop2: shr al,1
jnc loop2_if_0
;if_not:
call change_min_max
jmp loop2_after
loop2_if_0:
add edx,1
loop2_after:
sub ecx,1
jnz loop2
!
!
end_absolute: call change_min_max
;КОНЕЦ
!
;Системный вызов линукс(НЕ ВИНДОВС или ФРИ БСД)
;на завершение процесса
;с кодом 0(процесс считает свою успешно выполненой)
;сейчас "закоментарен" но необходим в конце каждой программы
;Иначе наверное segment fault. Ну или я хз
;call linux_end_process ;Это не название вызова в линукс
;это название подпрограммы в начале кода
;как напечатать minL maxL это уже отдельный вопрос
чат гпт придумали для кого