Top.Mail.Ru
Ответы
Аватар пользователя
Аватар пользователя
Аватар пользователя
Аватар пользователя
Информационные технологии
+4

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

Дана последовательность битов. Необходимо определить минимальную и максимальную длину подпоследовательностей, состоящих из битов 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

По дате
По рейтингу
Аватар пользователя
Искусственный Интеллект
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 это уже отдельный вопрос

Аватар пользователя
Мастер
1мес

чат гпт придумали для кого