В одномерном динамическом массиве целых чисел дли...

Создано: 13 апреля 2025 г.

Отвечено с использованием O1 от Chat01

Вопрос

В одномерном динамическом массиве целых чисел длиной в слово четной размерности поменять местами первую половину массива со второй.

• Массив заполнить генератором случайных чисел на C++ и вывести его на экран.
сделай это задание на вкрапленном ассемблере.

Мысль

Mapping out array operations

The task involves using inline assembly in C++ to swap halves of an even-sized dynamic integer array, likely with a 16-bit word length.

Crafting array manipulations

I’m constructing a C++ program with inline assembly to swap halves of an even-sized dynamic integer array, leveraging MSVC style for x86 32-bit architecture.

Crafting the solution

I'm piecing together a concise code snippet with embedded assembly for an even-sized dynamic integer array, focusing on efficiency and clarity for MSVC inline assembly.

Crafting the swap

I’m detailing code that employs MSVC inline assembly to swap halves of an even-sized dynamic integer array, ensuring efficient array manipulation.

Finished reasoning

Ответ

Ниже приведён компактный пример для MSVC (x86, 32‑bit) с использованием встроенного ассемблера __asm.
Он создаёт динамический массив int чётной длины, заполняет его случайными числами, выводит, а затем полностью меняет местами первую и вторую половины массива на ассемблере.

cpp
#include <iostream> #include <cstdlib> #include <ctime> int main() { const int n = 16; // чётная длина (можно заменить на любое чётное число) int* a = new int[n]; // динамический массив std::srand(static_cast<unsigned>(std::time(nullptr))); for (int i = 0; i < n; ++i) // заполняем случайными числами a[i] = std::rand() % 100; std::cout << "Before swap:\n"; for (int i = 0; i < n; ++i) std::cout << a[i] << ' '; std::cout << "\n\n"; /*---------------------------------------------------- Меняем половины местами (инлайн‑ASM, MSVC, x86) ecx = n/2 –‑ количество обменов esi -> начало первой половины edi -> начало второй половины ----------------------------------------------------*/ __asm { mov esi, a ; esi = &a[0] mov ecx, n shr ecx, 1 ; ecx = n/2 (счётчик обменов) mov edi, esi add edi, ecx*4 ; edi = &a[n/2] swap_loop: mov eax, [esi] ; eax = a[i] xchg eax, [edi] ; eax <-> a[i + n/2] mov [esi], eax ; a[i] = прежнее a[i + n/2] add esi, 4 ; ++i add edi, 4 loop swap_loop ; пока ecx != 0 } std::cout << "After swap:\n"; for (int i = 0; i < n; ++i) std::cout << a[i] << ' '; std::cout << '\n'; delete[] a; return 0; }

Как это работает

  1. Генерация данных – стандартный rand() заполняет массив.
  2. Настройка регистров
    • esi — указатель на текущий элемент первой половины.
    • edi — указатель на «зеркальный» элемент второй половины.
    • ecx = n/2 — счётчик, одновременно равный количеству требуемых обменов.
  3. Цикл swap_loop
    • mov eax, [esi] – читаем левый элемент.
    • xchg eax, [edi] – обмениваем его с правым (второй половины).
    • mov [esi], eax – записываем полученное значение в левую позицию.
    • Сдвигаем оба указателя на 4 байта (один int) и повторяем, пока ecx не станет 0.
  4. После выхода из цикла половины массива полностью поменялись местами.

Важно: MSVC‑style inline assembly поддерживается только в 32‑битных сборках.
Для 64‑битных проектов используйте отдельный .asm‑файл или GCC‑style asm/__attribute__((naked)).


Вариант для GCC/Clang (AT&T синтаксис, x86‑64)

cpp
// ... тот же код генерации массива ... asm volatile( "mov %[ptr], %%rsi\n\t" // rsi = &a[0] "mov %[len], %%rcx\n\t" "shr $1, %%rcx\n\t" // rcx = n/2 "lea (%%rsi,%%rcx,4), %%rdi\n" // rdi = &a[n/2] "1:\n\t" "mov (%%rsi), %%eax\n\t" "xchg %%eax, (%%rdi)\n\t" "mov %%eax, (%%rsi)\n\t" "add $4, %%rsi\n\t" "add $4, %%rdi\n\t" "loop 1b\n\t" : : [ptr]"r"(a), [len]"r"(n) : "rsi", "rdi", "rcx", "rax", "memory" );

Оба варианта делают одно и то же; выберите тот, который подходит вашей среде.

Поделиться этим Q&A