1

我一直在研究一个对 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);
}
4

3 回答 3

6

没有什么可以“刷新”的。您的代码运行。 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]

更不用说在汇编中实现冒泡排序完全是浪费时间。改写:学习汇编很棒,但在任何重要的事情上都使用它是个坏主意。了解汇编最重要的事情之一是知道何时不需要使用它。您可能会经常发现您的编译器生成的内容已经足够好。我们也不要忘记,C 语言中的好算法将击败汇编中的坏算法,例如冒泡排序。

@Giorgio 在评论中也提出了一个很好的观点。您的程序集正在比较和排序字节。你想做这样的事情:

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.

注意我不确定这是否是唯一的问题,我没有太彻底地查看你的代码。

于 2011-09-15T17:43:03.043 回答
2

我也会试一试。

#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。这不是很好,有人看到更好的解决方案吗?

于 2011-09-15T18:13:50.540 回答
0

您似乎打算分配和输入一个n int值数组。(尽管您的内存大小malloc不正确,正如已经指出的那样)。

但随后您继续将您的数组排序为n 字节数组。为什么要对字节进行排序而不是对ints 进行排序?

即使您的排序算法正确实现(作为字节排序实现),最终结果看起来完全没有意义,因为您最终将数组打印为ints 数组。

首先确定您要尝试使用的是什么:ints 或字节(chars),然后相应地并始终如一地采取行动。

于 2011-09-15T17:50:00.227 回答