首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >装配-排列生成的问题

装配-排列生成的问题
EN

Stack Overflow用户
提问于 2021-07-24 14:35:47
回答 2查看 124关注 0票数 0

我试图列出所有的排列的第一个N自然数(N <= 6)与MSVC组装8086内嵌。我不能更改任何C程序,我只能管理汇编代码。这就是我所做的(并使用N <= 3),使用字典算法:

代码语言:javascript
复制
#include <stdio.h>
int main() {
// Variabili
int N=4;    // N <= 6
int Perm[4326];    // permutations array: the dimension is sufficient for N <= 6
int Num;     // At the end it must contains the number of generated permutations
// Assembler block
__asm
{
    XOR EAX, EAX    ; Reset EAX (permutations counter)
    MOV ECX, N        ; Put N into ECX
    CMP ECX, 1        ; Compare ECX and 1
    JBE Piccolo        ; If ECX <= 1 go to Piccolo (particular cases 1 and 0)
    DEC ECX        ; Decrement ECX (so ECX = N - 1)
    MOV EAX, N    ; Put N into EAX
    MaxPerm:
        MUL ECX            ; Do EDX:EAX = EAX * ECX
        LOOP MaxPerm    ; Loop to find permutations number
    MOV Num, EAX    ; Move EAX (permutations number) into Num
    MOV EAX, 1        ; Set EAX (permutations number) to 1
    MOV EBX, 0        ; Reset EBX (EBX = 0)
    MOV ECX, 1        ; Reset ECX
    CicloIniziale:
        DEC ECX                    ; Decrement ECX (to compare it with N)
        CMP ECX, N                ; Compare ECX and N
        JE Permutazione            ; If ECX == N the first permutation has been written, skip to the generation of the next ones
        INC ECX                    ; Else increment ECX
        MOV Perm[4*EBX], ECX    ; Insert ECX into the Perm array
        INC ECX                    ; Increment ECX
        INC EBX                    ; Increment EBX
        JMP CicloIniziale        ; Continue the loop
    Permutazione:
        XOR EAX, EAX    ; Local index
        XOR EBX, EBX    ; Previous permutation index
        MOV ECX, N        ; Current permutation index
        MOV EDI, 1        ; Value of k
        MOV ESI, 1        ; New position of k
        
        CicloPermutazione:
            CMP EAX, N                ; Compare ECX and EAX
            JE ResetPerm            ; If the end of the permutation has been reached, go to ResetPerm
            MOV EDX, Perm[4*EBX]    ; Otherwise save the element of the previous permutation in position EBX in EDX
            CMP EDX, EDI            ; Compare EDX and EDI
            JE ValoreUguale            ; If they are equal, then go to ValoreUguale
            CMP EAX, ESI            ; Otherwise compare EBX and ESI
            JE InserisciElSpostato    ; If it's time to move the item, go to InserisciElSpostato
            MOV Perm[4*ECX], EDX    ; Returns the value of the previous permutation to the new permutation
            ContinuaCiclo:
                INC EBX                    ; Increment the previous permutation index
                INC EAX                    ; Increment the local index
                INC ECX                    ; Increment the new permutation index
                JMP CicloPermutazione    ; Continue the loop
        
            InserisciElSpostato:
                MOV Perm[4*ECX], EDI    ; Put EDI in the new permutation
                MOV EDX, N                ; EDX = N
                DEC EDX                    ; EDX -= 1
                CMP ESI, EDX            ; Compare ESI and EDX
                JE ResettaK                ; If ESI == EDX go to ResettaK
                JMP ContinuaCiclo        ; Continue the loop
            
            ValoreUguale:
                CMP EAX, 0                ; Confronta EAX e 0
                JZ PrimaPos                ; If EAX == 0 (first position) go to PrimaPos
                MOV EDX, Perm[4*EBX+4]    ; Else save the element into position EBX - 1
                MOV Perm[4*ECX], EDX    ; Insert EDX in the new permutation
                JMP ContinuaCiclo        ; Continue the loop
                
                PrimaPos:
                    MOV EDX, Perm[4*EBX+4]    ; Save into EDX the element in position ECX + 1
                    MOV Perm[4*ECX], EDX    ; Insert EDX into the new permutation
                    JMP ContinuaCiclo        ; Continue the loop
            ResettaK:
                XOR ESI, ESI            ; Reset ESI
                MOV EDI, Perm[4*EDI]    ; EDI = Perm[EDI]
                JMP ContinuaCiclo        ; Continue the loop
            ResettaKN:
                CMP EDI, N            ; Compare EDI and N
                JNE ContinuaCiclo    ; if EDI != N then continue the loop
                JMP ResettaK        ; Else go to ResettaK
        ResetPerm:
            MOV EAX, Num            ; EAX = Num
            MUL DWORD PTR N            ; EAX *= N (Elements of number of all the permutations)
            CMP EAX, ECX            ; Compare EAX and ECX
            JE Fine                    ; If EAX == ECX (permutations done) then finish the program
            XOR EAX, EAX            ; Otherwise reset EAX
            INC ESI                    ; Increment k index
            JMP CicloPermutazione    ; Continue the loop
    Piccolo:            ; If N = 0 or N = 1, the only permutation that can exists is made by only 1 element
        MOV Num, 1
        MOV Perm[0], ECX
        
    Fine:
}
// Print
{
    int i,j,k;
    printf("%d permutations of the first %d natural numbers\n", Num, N);
    for (i=k=0;i<Num;i++)
    {
        for (j=0;j<N;j++)
        {
            printf("%3d",Perm[k++]);
        }
        printf("\n");
    }
}
return 0;
}

问题是这个程序只适用于N <= 3,而我没有发现这个问题!这些是我得到的输出:

N=3及以下工作正常:

代码语言:javascript
复制
6 permutations of the first 3 natural numbers
1  2  3
2  1  3
2  3  1
3  2  1
3  1  2
1  3  2

N=4(与5和6相同):

代码语言:javascript
复制
24 permutations of the first 4 natural numbers
1  2  3  4
2  1  3  4
2  3  1  4
2  3  4  1
3  2  4  1
3  4  2  1
3  4  1  2
4  3  1  2
4  1  3  2
4  1  2  3
1  4  2  3
1  2  4  3
1  2  3  4
1  3  3  4
1  3  2  4
1  3  4  2
1  4  4  2
1  4  3  2
1  4  2  3
1  2  2  3
1  2  4  3
1  2  3  4
1  3  3  4
1  3  2  4

正如你所看到的,在第一个周期的最后一个排列之后,下一个周期是混乱的.

你能帮帮我吗?谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-19 18:30:08

最后,我成功地编写了一个C程序,它使用next_permutation STD库的C++函数的算法来完成工作。然后,我在哥德波特 (联机编译器)的帮助下将C代码翻译成程序集。

所以:

  1. 使用next_permutation函数编写C程序:https://godbolt.org/z/7avGaWfha
  2. 将主:https://godbolt.org/z/7z9MGWefK中的所有函数都压平
  3. 最后,在哥德波特的大力帮助下,把它翻译成汇编。
票数 1
EN

Stack Overflow用户

发布于 2021-07-25 21:05:40

您已经编写了几行代码与附带的注释不匹配的代码。如果我是你,我会怀疑那里可能有错误。

CMP EDX,N;比较ECX和EDX CMP EDX,ESI;否则比较EBX和ESI MOV EDX,Perm4*EBX+4;否则将元素保存到EBX -1 MOV EDX,Perm4*EBX+4位置;将位于ECX +1位置的元素保存到EDX中。

这将是与注释匹配的代码:

代码语言:javascript
复制
cmp ecx, eax
cmp ebx, esi
mov edx, Perm[4*ebx - 4]  ; 'save' == 'save into EDX' (*)
mov edx, Perm[4*ecx + 4]

我并不是说这些会解决问题,因为也许你的评论是错误的,你的代码也是正确的。

(*)与其使用令人费解的短语“保存到EDX",不如将其写为"load EDX with/from”。

您已经成功地编写了许多冗余注释

以下是其中的一小部分:

MOV EAX,N;将N放入EAX MOV EBX,0;重置EBX (EBX = 0) CMP ECX,1;比较ECX和1 INC;增量ECX ECX;增量EBX MOV EDX,N;EDX =N DEC EDX;EDX -= 1 CMP ESI,EDX;比较ESI和EDX JE ResettaK;如果ESI == EDX转到ResettaK

帮自己个忙,别再写这些多余的评论了。它们使任何人(包括你自己)更难理解代码。

最近的一篇博客文章讨论了编写代码注释的主题:https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68510978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档