В двухбайтной ячейке памяти записана последовательность нулей и единиц. С помощью битовых операций переставьте биты так чтобы сначала шли все единицы, а затем все нули. (реализуется, как ассемблерные вставки в С++)
Реализовал код уже на ассемблере:
_asm
{
mov bx, 0
mov ax, i
mov cx, 16 //Счетчик
m1: //цикл
shl ax, 1 //Логический сдвиг влево на одну клетку
adc bx, 0
loop m1
cmp bx, 0; //Если единиц нет
jz m2
mov cx, bx
m0 :
shl ax, 1 //Логический сдвиг влево на одну клетку
add ax, 1
loop m0
m2 :
mov s, ax
}
Проблема в том, что также нужна часть на С++. А с этим как раз и возникает проблема, ибо непонятно, как вводить эту последовательность нулей и единиц (точнее, какой тип указать для них). Также пока непонятно, как реализовать программу для сдвига всех единиц и нулей на С++.
Код:
#include <iostream>
#include <bitset>
int main()
{
unsigned short ref = 0x0F0F, res = 0x0000;
asm volatile (
"mov $0, %%bx \n"
"mov %1, %%ax \n"
"mov $16, %%cx \n"
"m1: \n"
" shl $1, %%ax \n"
" adc $0, %%bx \n"
" dec %%cx \n"
" jnz m1 \n"
"cmp $0, %%bx \n"
"jz m2 \n"
"mov %%bx, %%cx \n"
"m0: \n"
" shl $1, %%ax \n"
" add $1, %%ax \n"
" dec %%cx \n"
" jnz m0 \n"
"m2: \n"
" xchg %%al, %%ah \n"
" mov %%ax, %0 \n"
:"=r"(res) // выходные параметры (output operands)
:"r"(ref) // входные параметры (input operands)
:);
std::bitset<16> ref_bs { ref }, res_bs { res };
std::cout << "ref = (" << ref << ") " << ref_bs << ' '
<< "res = (" << res << ") " << res_bs << '\n';
return 0;
}
Я немного подправил Ваш код:
xchg %%al, %%ah
, в противном случае единицы находились в %al, а не %ah.
UPD.: я обнаружил, что я обманул Вас вчера - xchg сработал только потому, что я подобрал "удобное" число. Правильное решение заключается в следующем - вместо того, чтобы делать сдвиг влево и добавлять единицу:
" shl $1, %%ax \n"
" add $1, %%ax \n"
, мы будем делать сдвиг вправо и добавлять 0x8000:
" shr $1, %%ax \n"
" add $0x8000, %%ax \n"
Обновленный пример в wandbox.
Продвижение своими сайтами как стратегия роста и независимости