2010-10-26 69 views
0

我试图用汇编语言编写函数排序。它将对二维数组进行排序,使得行现在将按照字母顺序包含数据。 我尝试了很多东西,但它实际上超出了我目前的知识范围。 这里是我试过到目前为止...对程序集中的字符串进行排序

.386 
public _Sort 
.model flat 
.code 
_Sort proc 

    push ebp 
    mov ebp, esp 
    push esi 
    push edi 

    mov edi, [esp + 4] ; address of destination array 
    mov esi, [esp + 8] ; address of source array 
    mov ecx, [esp + 16] ; # of elements to mov 
    cld 
    rep movsd 
L1: 
    mov eax, [esi] 
    cmp [esi + 8], eax 
    jg L2 
    xchg eax, [esi + 8] 
    mov [esi], eax 
L2: 
    pop edi 
    pop esi 
    pop ebp 

    ret  
_Sort endp 
end 

这里的C++代码...

#include <iostream> 

using namespace std; 

extern "C" int Sort (char [] [20], int, int); 

void main() 
    { 
    char Strings [10] [20] 
        = { "One", 
         "Two", 
         "Three", 
         "Four", 
         "Five", 
         "Six", 
         "Seven", 
         "Eight", 
         "Nine", 
         "Ten" }; 
    int i; 
    cout << "Unsorted Strings are" << endl; 
    for (i = 0; i < 10; i++) 
     cout << '\t' << Strings [i] << endl; 
    Sort (Strings, 10, 20); 
    cout << "Sorted Strings are" << endl; 
    for (i = 0; i < 10; i++) 
     cout << '\t' << Strings [i] << endl; 
    } 

我不知道我的组装没有任何意义,我们对此深感抱歉。

回答

2

您将需要在函数/过程中构建汇编代码,就像您使用其他语言编写代码一样。就像在C中一样,字符串比较,复制等等,都需要在函数中完成。只是举例:

; compares [esi] to [edi], returns +, 0 or - to indicate order 
; inputs: esi, edi: addresses of strings 
; destroys: esi, edi, edx 
; 
strcmp_int proc 
    jmp short start 
loop_top: 
    inc esi 
    inc edi 
start: 
    movsx eax, byte ptr [esi] 
    movsx edx, byte ptr [edi] 
    test edx, edx 
    jz @f 
    sub eax, edx 
    jz loop_top 
    ret 
@@: 
    sub eax, edx 
    ret 
strcmp_int endp 

[警告:此代码不一定打算用作-是 - 只是种功能你通常需要编写做这样的一个示例汇编语言工作。由于我写了很多汇编语言,所以你可以在现代处理器上做得更好 - 至少对于单纯以汇编语言完成的事情,你通常希望把结果放在标志中,而不是 -/0/+在像strcmp(和这个)产生的寄存器中。但是请注意,这确实返回由最后sub]

又见Why is memcmp so much faster than a for loop check?了一些链接优化的实现(SSE2/AVX2)显式长度的字符串,设置标志这可以更快的中长期串。一般优化链接,请参阅the x86 tag wiki

您的sort将取决于您决定实施的排序算法。显然,Quicksort看起来不像插入排序。然而,主要观点很简单:不要试图将其编写成单一的,整体式的代码块—将其分解成易于编写和理解的代码段。

+0

'lodsb'已经增加了'esi'。使用'movzx eax,[esi]'来提高效率('lodsb'在Intel CPU上是3 uops,与'inc' /'movzx'不相称)。还可以使用'cmp al,[edi]'代替sub,所以它可以在更多的CPU上与'jz'进行宏观融合。 – 2017-11-26 10:57:45

+0

此外,如果它们等于终止'0'>,它将超过字符串的末尾。< – 2017-11-26 10:58:34

+0

显然,为了提高效率,您应该比较双字或qword(或更好地使用SSE2)。使用SSE2,可以很容易地并行检查每个字节是否为'0',但对于普通整数代码,您可以使用https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord。 (如果两个隐含长度的字符串相互错位,那么更大的负载会变得非常棘手。[这并不像使用'strlen'进行对齐加载那样简单](https://stackoverflow.com/questions/37800739/它是安全可读的 - 过去 - 在同一页上的一个缓冲区在x86和x64)。) – 2017-11-26 11:03:43

相关问题