подсчет количества нулей и единиц в байте - PullRequest
0 голосов
/ 27 февраля 2019

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

MOV AL,1
MOV CX,08H
MOV BX,0000H
MOV DX,0000H

Zero:


SHR AL,01H

JZ ero

JNZ ZrO

ero: INC BX

ZrO: INC DX


LOOP Zero

hlt

Программа не дает правильного ответа.Есть догадки, где я не прав?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Часто, когда вы пишете на ассемблере, интересно посмотреть на возможные оптимизации.Используя цикл, вы используете флаги Z и C следующим образом:

    MOV AL, <your value>
    MOV BL, 8
    CLC
Loop:
    SBB BL, 0
    SHR AL, 1
    JNZ Loop
Done:
    SBB BL, 0
    ; result is in BL
    HLT

Более быстрый способ на старых процессорах состоит в том, чтобы иметь таблицу 256 байтов и выполнить поиск.Как уже упоминалось vitsoft, на современных процессорах использование инструкции POPCNT, вероятно, является самым быстрым (для подсчета всех битов 64-битного регистра в аппаратном обеспечении требуется один такт).

Теперь, если вам нужно знать,точное время, мой цикл не практичен, потому что он будет варьироваться в зависимости от AL.Еще один способ сделать это быстро - развернуть цикл:

    MOV AL, <your value>
    MOV BL, 8
    SHR AL, 1    ; 1
    SBB BL, 0
    SHR AL, 1    ; 2
    SBB BL, 0
    SHR AL, 1    ; 3
    SBB BL, 0
    SHR AL, 1    ; 4
    SBB BL, 0
    SHR AL, 1    ; 5
    SBB BL, 0
    SHR AL, 1    ; 6
    SBB BL, 0
    SHR AL, 1    ; 7
    SBB BL, 0
    SHR AL, 1    ; 8
    SBB BL, 0
    HLT

Это практично, потому что у вас ноль ветвей.Современные процессоры так любят (хотя в данном случае, поскольку мы имеем дело только с 2 регистрами, я не думаю, что это огромное преимущество).

0 голосов
/ 28 февраля 2019

Бит, который смещен из AL, переходит в флаг переноса, а не в флаг нуля.Измените условные переходы:

    MOV AL,1     ; An investigated byte.    
    MOV CX,08H   ; Number of bits in the byte. 
    MOV BX,0000H ; Result: number of 1s.
    MOV DX,0000H ; Result: number of 0s.
Zero:SHR AL,01H  ; Shift the byte, least significant bit to CF.
    JNC ZrO
ero:INC BX      ; Count 1s. 
    JMP Skip
ZrO:INC DX      ; Count 0s.
Skip:LOOP Zero   ; Repeat CX times.
    hlt

Кстати, есть специальная инструкция для этой задачи на новых процессорах Intel (NEHALEM): https://www.felixcloutier.com/x86/popcnt

    MOV AL,1     ; An investigated byte.  
    XOR AH,AH    
    POPCNT BX,AX ; Count the number of 1s in AX and put result to BX.
    MOV DX,8
    SUB DX,BX    ; The number of 0s in AL is 8-BX.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...