Консультация № 146260
06.10.2008, 21:01
0.00 руб.
0 15 2
Доброго времени суток, есть вопросик, имеется переменная типа dd и нужно поменять местами соседние разряды, причем четные с четными, нечетные с нечетными ( было 12345678 должно стать 34567812 ) пожалуйста подскажите как это сделать... спасибо.

Обсуждение

давно
Старший Модератор
31795
6196
06.10.2008, 21:58
общий
Если данные в 16-ой системе.
То единственное, что напрашивается это циклический сдвиг влево на 8: ROL EAX,8
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
07.10.2008, 09:43
общий
Как-то формулировка вопроса не вяжется с приведенным примером...
На мой взгляд, формулировка вопроса подразумевает поменять местами биты...
Уточните, какие имеются в виду разряды: биты, десятичные, 16-ричные?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
07.10.2008, 10:53
общий
это ответ
Здравствуйте, Sacha!
Вот в приложении простейшее решение Вашей задачи.
Решается с помощью множителей nums
Я не понял, честно говоря, почему именно такое число должно получиться, но получил

Приложение:
; Title NEW
.model tiny
.386
LOCALS @@
.code
org 100h
start:
mov ax, 3
int 10h

mov eax, 12345678
CALL writeDWORD_DEC

CALL invert
CALL CRLF
CALL writeDWORD_DEC



lea dx, msg_press
mov ah, 9
int 21h
xor ax, ax
int 16h
int 20h

invert proc
; ОЖИДАЕТ слово для изменения в EAX
; организована аналогично writeDWORD_DEC
; только не показывает, а заполняет массив nums
; а из него формирует слово с помощью массива множителей mults
; и возвращает в EAX
push ebx
push ecx
push edx
push esi
push edi
mov ebx, 10
xor ecx, ecx
@@1:
xor edx, edx
div ebx
inc ecx
push edx
or eax, eax
jnz @@1
lea si, mults
cld
xor edi, edi ; временный аккумулятор числа
@@2:
lodsd
pop ebx
mul ebx
cwd
add edi, eax
LOOP @@2
mov eax, edi
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
invert endp

writeDWORD_DEC proc
; двойное слово в EAX показывает
push eax
push ebx
push ecx
push edx
mov ebx, 10
xor ecx, ecx
@@1:
xor edx, edx
div ebx
inc ecx
push edx
or eax, eax
jnz @@1
@@2:
pop eax
add al, '0'
int 29h
LOOP @@2
pop edx
pop ecx
pop ebx
pop eax
ret
writeDWORD_DEC endp

CRLF proc
push ax
mov al, 10
int 29h
mov al, 13
int 29h
pop ax
ret
CRLF endp

; с помощью этого массива любой порядок можно организовать ;))
mults dd 10, 1, 10000000, 1000000, 100000, 10000, 1000, 100
msg_press db 13,10,'Press any key ...$'

end start
Неизвестный
07.10.2008, 20:56
общий
да нужно поменять местами биты
Неизвестный
07.10.2008, 21:00
общий
Boriss спасибо за ответ только можно сказать непонятно ничего( я изучаю Assembler 4 недели), если можно напишите пожалуйста цикл который меняет местами разряды (четные с четными нечетные с нечетными)
давно
Посетитель
7438
7205
08.10.2008, 09:45
общий
Так...Задаю уточняющий вопрос еще раз:
Если меняем местами биты, то вопрос, с какими соседними меняем?
Могу предположить, что в 16-ричной тетраде, или нет?
Например, если рассмотрим один байт (3 остальных аналогично):
Пусть имеем байт ababcdcd B , в котором a,b,c,d обозначают биты 0 или 1.
Требуется поменять местами биты, обозначенные одинаковыми буковками.
Т.е. надо получить babadcdc B. Так?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
08.10.2008, 10:55
общий
Делает все процедура invert .
В ней я раскладываю число на цифры (как при выводе числа в десятичном виде): делю на EBX=1 0 (это и есть основание числа), запоминаю остатки в стек PUSH EDX . И заодно подсчитываю число запомненных INC ECX .
Потом извлекаю из стека POP EBX и умножаю на коэффициент их таблицы LODSD - считывает в EAX содержимое памяти по адресу ES:ESI и увеличивает ESI на 4 (следующее двойное слово). Результат умножения добавляют в аккумулятор
Фактически, реализуется формула:
1234 = 4*1 + 3*10 + 2*100 + 1 *1000
чтобы поменять местами, можно
4*10 + 3*1 и т.д.
Неизвестный
08.10.2008, 10:57
общий
То есть, результирующий порядок определяется содержимым массива mults
Неизвестный
08.10.2008, 12:40
общий
Лысков Игорь Витальевич, ну да почти все так, например если нам дано abcdeg то должны получить (расписываю пошагам) abcdeg ->cbadeg ->cdabeg -> cdebag -> cdegab
Неизвестный
08.10.2008, 13:01
общий
И в моем варианте это тоже возможно, только основание будет 16, да и вывод не десятичный, а более просто реализуемый
давно
Посетитель
7438
7205
08.10.2008, 13:02
общий
Вопрос: нужен результат или важен сам процесс?
Дело в том, все сводится в конце концов к тому, что два старших бита перемещаются на место двух младших,
Поэтому достаточно просто сдвинуть двойное слово циклически влево на два бита rol eax,2
Все! Задача решена!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
08.10.2008, 14:15
общий
все дело в том что важен сам процесс и хорошо если сдвиг будет организован с помощью логических операций
Неизвестный
08.10.2008, 14:16
общий
Boriss спвасибо за программу но мне важнее понять сам цикл а процесс ввода выввода результата меня совсем не интересует и ваш предложенный вариантс умножением мне тоже не очень подходит
давно
Посетитель
7438
7205
08.10.2008, 15:32
общий
это ответ
Здравствуйте, Sacha!
Например, так, как в приложении.
Для удобства используем 32-разрядные регистры.


Приложение:
.model tiny
.386
.code
.startup
mov eax, 12345678h ;наша переменная
mov cx, 30 ;число циклов на 2 меньше чем разрядность переменной
mov edx, 80000000h ;маска первого бита
mov esi, 5fffffffh ;маска для обнуления обоих битов
main_loop:
mov ebx, edx ;маска первого бита
and ebx, eax ;получим первый бит
shr ebx, 2 ;поставим его на место второго бита
shr edx, 2 ;сформируем маску второго бита
mov edi, edx ;маска второго бита
and edi, eax ;получим второй бит
shl edi, 2 ;поставим его на место первого бита
and eax, esi ;обнуляем биты на обоих местах
or eax, ebx ;записываем бывший первый на место второго
or eax, edi ;а бывший второй на место первого
shl edx, 1 ;формируем маску первого бита для следующей итерации
ror esi, 1 ;маска для обнуления для следующей итерации
loop main_loop ;зацикливаем
.exit 0
end
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
08.10.2008, 17:39
общий
спасибо
Форма ответа