Как обновить массив C после использования сборки для сортировки - PullRequest
1 голос
/ 15 сентября 2011

Я работал над программой, которая будет выполнять пузырьковую сортировку для n целых чисел. Я врезался в стену, так как не знаю, как обновить массив после завершения операции ассемблера. Любые предложения будут великолепны.

#include <stdio.h>
#include <stdlib.h>

int n;
int *input;
int output;
int i;

int main(void)
{
scanf("%d", &n);

input = (int *)malloc(sizeof(n));

for (i = 0; i < n; i++)
{
    scanf("%d", &input[i]);
}

__asm
{
    mov ebx, input
    mov esi, n


outer_loop:
    dec esi
    jz end_outer
    mov edi, n

inner_loop:
    dec edi
    jz outer_loop

compare:
    mov al, [ebx + edi - 1]
    mov dl, [ebx + edi]
    cmp al, dl
    jnl inner_loop

swap:
    mov [ebx + edi], al
    mov [ ebx + edi - 1], dl
    jmp inner_loop

end_outer:



}

for (i = 0; i < n; i++)
{
    printf("%d\n", input[i]);
}
scanf("%d", &output);
}

Ответы [ 3 ]

6 голосов
/ 15 сентября 2011

Нечего "обновлять". Ваш код работает. ebx содержит input и все. (Подсказка: ваш код на C также преобразуется в сборку. Просмотр того, что ваш компилятор генерирует через дизассемблер, может дать вам некоторое представление.)

Тем не менее, я вижу некоторые проблемы:

input = (int *)malloc(sizeof(n));

Это распределение недостаточно велико, и ваша программа аварийно завершит работу. Вы хотите выделить sizeof(int) * n. Также следует проверить распределение на наличие ошибок.

mov al, [ebx + edi - 1]
mov dl, [ebx + edi]
cmp al, dl

Вид многословия. Вы должны уметь сравнивать регистр с памятью. (напр. cmp al, byte [ebx + edi])

Не говоря уже о том, что внедрение пузырьковой сортировки в сборке является полной тратой времени. Перефразировка: Изучение сборки великолепно, но было бы плохой идеей использовать это во всем, что имеет значение. Одна из самых важных вещей в знании ассемблера - это знание, когда вам не нужно его использовать. Вы, вероятно, очень часто обнаружите, что то, что генерирует ваш компилятор, достаточно хорошо. Давайте также не будем забывать, что хороший алгоритм в Си превзойдет плохой алгоритм в ассемблере, такой как пузырьковая сортировка.

@ Джорджио также поднимает хороший вопрос в комментариях. Ваша сборка сравнивает и сортирует байты. Вы хотите делать такие вещи:

mov eax, [ebx + edi - 4]    ; assumes edi is a byte offset, see next comment
mov edx, [ebx + edi]

И вместо dec edi и т. Д. Вы хотите сделать:

sub edi, 4

Для использования 32-битных величин необходимо также выполнить перестановку.

Это, конечно, предполагается, что int - это 32 бита, что может быть не так. Если вы используете (нестандартную) встроенную сборку, вероятно, это справедливо - это означает, что вы уже нацелены на определенный компилятор. (Исходя из синтаксиса, я бы сказал, VC ++) Nitpickers могут сказать, что вы должны использовать int32_t вместо int.

Примечание. Я не уверен, что это единственная проблема, я не слишком внимательно изучил ваш код.

2 голосов
/ 15 сентября 2011

Я также попробую.

#include <stdio.h>
#include <stdlib.h>

int n;
int *input;
int output;
int i;
int s;

int main(void)
{
    s = sizeof(int);
    scanf("%d", &n);

    input = (int *)malloc(sizeof(n));

    for (i = 0; i < n; i++)
    {
        scanf("%d", &input[i]);
    }

    __asm
    {
        mov ecx, s
        mov ebx, input
        mov esi, n
        mul esi, ecx

    outer_loop:
        sub esi, ecx
        jz end_outer
        mov edi, esi

    inner_loop:
        sub edi, ecx
        jz outer_loop

    compare:
        mov edx, [ebx + edi]
        sub edi, ecx
        mov eax, [ebx + edi]
        add edi, ecx

        cmp eax, edx
    jnl inner_loop

    swap:
        mov [ebx + edi], eax
        sub edi, ecx
        mov [ebx + edi], edx
        add edi, ecx
        jmp inner_loop

    end_outer:
    }

    for (i = 0; i < n; i++)
    {
        printf("%d\n", input[i]);
    }

    scanf("%d", &output);
}

Я использовал переменную s для хранения размера целого числа.Насколько мне известно, нельзя использовать косвенное указание типа

mov eax, [ebx + edi + ecx]

, поэтому мне пришлось добавлять отдельные add и sub.Это не очень приятно, кто-нибудь видит лучшее решение?

0 голосов
/ 15 сентября 2011

Вы, похоже, намереваетесь выделить и ввести массив значений n int. (Хотя размер памяти в вашем malloc указан неверно, как уже было отмечено).

Но затем вы продолжаете сортировать свой массив как массив n байт . Почему вы сортируете байты вместо int с?

Даже если ваш алгоритм сортировки реализован правильно (как реализация сортировки байтов), конечный результат будет выглядеть совершенно бессмысленным, так как вы печатаете свой массив как массив int s в конце.

Сначала решите, с чем вы пытаетесь работать: int с или байтами (char с), а затем действуйте соответственно и последовательно.

...