- Asmworld - http://asmworld.ru -

Учебный курс. Часть 19. Циклический сдвиг

Posted By xrnd On 13.05.2010 @ 13:56 In Учебный курс | 58 Comments

Циклический сдвиг отличается от линейного тем, что выдвигаемые с одного конца биты вдвигаются с другой стороны, то есть движутся по кольцу. В процессора x86 существует 2 вида циклического сдвига: простой и через флаг переноса (CF). У всех команд, рассматриваемых в этой части учебного курса, по 2 операнда, таких же, как у команд линейного сдвига. Первый операнд — сдвигаемое значение и место для записи результата. Второй операнд — счётчик сдвигов, который может находится в регистре CL или указываться непосредственно.

Простой циклический сдвиг

Циклический сдвиг вправо выполняется командой ROR [1], а влево — командой ROL [2]. Схема работы этих команд представлена на рисунке (на примере 8-битного операнда):

Значение последнего выдвигаемого бита копируется в флаг CF. Для сдвигов на 1 бит устанавливается флаг OF, если в результате сдвига изменяется знаковый бит операнда. (Честно говоря, не помню, чтобы я этим когда-то пользовался. Но может вам пригодится :-) ) Примеры использования команд:

    rol bl,1         ;Циклический сдвиг BL на 1 бит влево
    ror word[si],5   ;Циклический сдвиг слова по адресу в SI на 5 бит вправо
    rol ax,cl        ;Циклический свдиг AX на CL бит влево

Циклический сдвиг через флаг переноса

Отличие от простого циклического сдвига в том, что флаг CF участвует в сдвиге наравне с битами операнда. При сдвиге на 1 бит выдвигаемый бит помещается в CF, а значение CF вдвигается в операнд с другой стороны. При сдвиге на несколько бит эта операция повторяется многократно. Циклический сдвиг через флаг переноса выполняется командами RCR [3] (вправо) и RCL [4] (влево).

Опять же для сдвигов на 1 бит устанавливается флаг OF, если в результате сдвига изменяется знаковый бит операнда. Примеры использования команд:

    rcr dh,3         ;Цикл. сдвиг DH на 3 бита вправо через флаг CF
    rcl byte[bx],cl  ;Цикл. сдвиг байта по адресу в BX на CL бит влево через флаг CF
    rcl dx,1         ;Цикл. сдвиг DX на 1 бит влево через флаг CF

Пример программы

В качестве примера напишем программу для подсчёта единичных битов в байте. Для анализа битов используется команда ROL [2] в цикле. Цикл выполняется 8 раз — по числу битов в байте. Если очередной бит равен 1, то выполняем инкремент счётчика единичных битов.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use16             ;Генерировать 16-битный код
org 100h          ;Программа начинается с адреса 100h
 
    mov al,[x]    ;AL = x
    xor bl,bl     ;BL = 0 (Здесь будем считать единичные биты)
    mov cx,8      ;Инициализация счётчика цикла
lp:
    rol al,1      ;Цилический сдвиг AL на 1 бит влево
    jnc bit0      ;Переход, если CF=0
    inc bl        ;Инкремент счетчика единичных битов
bit0:
    loop lp       ;Команда цикла
    mov [n],bl    ;Сохраняем результат в n
 
    mov ax,4C00h  ;\
    int 21h       ;/ Завершение программы
;----------------------------------------------------------------------
x  db 89h         ;Байт
n  db ?           ;Количество единичных битов в байте

Эту программу можно немного оптимизировать. Во-первых, использовать вместо условного перехода команду ADC [5] со нулевым вторым операндом. Это позволит прибавить 1, если CF=1 и прибавить 0, если CF=0. Во-вторых, считать единичные биты можно в регистре AH, а обнулить его в начале с помощью команды MOVZX [6], совместив с загрузкой байта в регистр AL. Ноль для команды ADC [5] можно взять в регистре CH, это делает команду короче и быстрее, чем при использовании непосредственного операнда. CH равен 0 во время выполнения цикла, так как CX изменяется от 8 до 0. Вот что получилось в итоге:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use16             ;Генерировать 16-битный код
org 100h          ;Программа начинается с адреса 100h
 
    movzx ax,[x]  ;AL = x, AH = 0
    mov cx,8      ;Инициализация счётчика цикла
lp:
    rol al,1      ;Цилический сдвиг AL на 1 бит влево
    adc ah,ch     ;Прибавляем флаг CF к AH, так как CH = 0
    loop lp       ;Команда цикла
    mov [n],bl    ;Сохраняем результат в n
 
    mov ax,4C00h  ;\
    int 21h       ;/ Завершение программы
;----------------------------------------------------------------------
x  db 89h         ;Байт
n  db ?           ;Количество единичных битов в байте

Всего 6 команд для подсчета битов в байте. А попробуйте написать то же самое на языке высокого уровня ;)

Упражнение

Объявите в программе строку. Длина строки должна быть больше 8 символов и храниться в байте без знака. Напишите цикл для шифрования строки по алгоритму: первый символ циклически сдвигается вправо на 1 бит, второй символ — на 2 бита, …, 7-й — на 7 битов, 8-й — снова на 1 бит, 9-й на 2 бита и т.д. Затем напишите цикл для расшифровки строки и выведите её на экран.

Следующая часть » [7]


Article printed from Asmworld: http://asmworld.ru

URL to article: http://asmworld.ru/uchebnyj-kurs/019-ciklicheskij-sdvig/

URLs in this post:

[1] ROR: http://asmworld.ru/spravochnik-komand/ror

[2] ROL: http://asmworld.ru/spravochnik-komand/rol

[3] RCR: http://asmworld.ru/spravochnik-komand/rcr

[4] RCL: http://asmworld.ru/spravochnik-komand/rcl

[5] ADC: http://asmworld.ru/spravochnik-komand/adc

[6] MOVZX: http://asmworld.ru/spravochnik-komand/movzx

[7] Следующая часть »: http://asmworld.ru/uchebnyj-kurs/020-stek/

Copyright © 2009-2010 Asmworld. All rights reserved.