2
\$\begingroup\$

So, a long time ago, I've made a program that prints all the permutations of digits of a number in AEC. Now I have refactored it a bit, and I would be interested in what you think about it.

;Advanced example: implementing the permutation algorithm.
AsmStart
    debug=0
    macro pushIntegerToTheSystemStack x
    {
        sub esp,4
        fld dword [x]
        fistp dword [esp]
    }
    macro pushPointerToTheSystemStack x
    {
        sub esp,4
        lea ebx,[x]
        mov [esp],ebx
    }
    macro pushStringToTheSystemStack x
    {
        sub esp,4
        mov dword [esp],x
    }
    format PE console
    entry start

    include 'win32a.inc'

    section '.text' code executable
    start:
    jmp enterNumber$
        enterNumber db "Enter a whole number (1 - 1'000'000).",10,0
    enterNumber$:
    pushStringToTheSystemStack enterNumber
    call [printf]
    pushPointerToTheSystemStack original
    jmp floatSign$
        floatSign db "%f",0
    floatSign$:
    pushStringToTheSystemStack floatSign
    call [scanf]
    jmp permutationString$
        permutationString db "The permutations of its digits are:",10,0
    permutationString$:
    pushStringToTheSystemStack permutationString
    call [printf]
AsmEnd
numberOfPermutations:=0
numberOfDigits:=0
i:=0
While i<10
    countDigits[i] := 0
    i:=i+1
EndWhile
While original>0
    numberOfDigits := numberOfDigits + 1
    lastDigit := mod (original, 10)
    countDigits [lastDigit] := countDigits (lastDigit) + 1
    original := (original - lastDigit) / 10
EndWhile
AsmStart
    if debug=1
AsmEnd
        i:=0
        While i<10
            subscript:=4*i
            AsmStart
                fld dword [subscript]
                fistp dword [subscript]
                mov ebx,[subscript]
                pushIntegerToTheSystemStack (countDigits+ebx)
                pushStringToTheSystemStack integerSign
                call [printf]
            AsmEnd
            i:=i+1
        EndWhile
        AsmStart
            pushStringToTheSystemStack newLineString
            call [printf]
        AsmEnd
AsmStart
end if
AsmEnd
topOfMyStack:=1
myStack [ (numberOfDigits + 1) ] := 0
While topOfMyStack>0
    currentNumberOfDigits := myStack ( topOfMyStack * ( numberOfDigits + 1 ) )
    i:=0
    While i<currentNumberOfDigits
        currentNumber ( i ) := myStack ( topOfMyStack * ( numberOfDigits + 1 ) + ( i + 1 ) )
        i:=i+1
    EndWhile
    AsmStart
        if debug=1
    AsmEnd
            i:=0
            While i<currentNumberOfDigits
                subscript:=i*4
                AsmStart
                    fld dword [subscript]
                    fistp dword [subscript]
                    mov ebx,[subscript]
                    pushIntegerToTheSystemStack (currentNumber+ebx)
                    pushStringToTheSystemStack integerSign
                    call [printf]
                AsmEnd
                i:=i+1
            EndWhile
            AsmStart
                pushStringToTheSystemStack newLineString
                call [printf]
            AsmEnd
    AsmStart
        end if
    AsmEnd
    topOfMyStack:=topOfMyStack-1
    If currentNumberOfDigits=numberOfDigits
        numberOfPermutations:=numberOfPermutations+1
        i:=0
        While i<numberOfDigits
            subscript:=i*4
            AsmStart
                fld dword [subscript]
                fistp dword [subscript]
                mov ebx,[subscript]
                pushIntegerToTheSystemStack (currentNumber+ebx)
                pushStringToTheSystemStack integerSign
                call [printf]
            AsmEnd
            i:=i+1
        EndWhile
        AsmStart
            pushStringToTheSystemStack newLineString
            call [printf]
        AsmEnd
    Else
        i:=0
        While i<10
            counter:=0
            j:=0
            While j<currentNumberOfDigits
                If currentNumber(j)=i
                    counter:=counter+1
                EndIf
                j:=j+1
            EndWhile
            If counter < countDigits(i)
                topOfMyStack := topOfMyStack + 1
                myStack (topOfMyStack * (numberOfDigits + 1) ) := currentNumberOfDigits + 1
                j:=0
                While j < currentNumberOfDigits
                    myStack (topOfMyStack * (numberOfDigits + 1) + (j + 1)) := currentNumber (j)
                    j:=j+1
                EndWhile
                myStack (topOfMyStack * (numberOfDigits + 1) + (j + 1) ) := i
            EndIf
            i:=i+1
        EndWhile
    EndIf
EndWhile
AsmStart
    jmp numberOfPermutationsString$
    numberOfPermutationsString:
        db "The total number of permutations was: %d",10,0
    numberOfPermutationsString$:
    pushIntegerToTheSystemStack numberOfPermutations
    pushStringToTheSystemStack numberOfPermutationsString
    call [printf]
    invoke system,_pause
    invoke exit,0

    _pause db "PAUSE",0
    integerSign db "%d",0
    newLineString db 10,0

    section '.rdata' readable writable
        original dd ?
        result dd ?
        lastDigit dd ?
        numberOfDigits dd ?
        countDigits dd 11 dup(?)
        subscript dd ?
        myStack dd 1000 dup(?)
        topOfMyStack dd ?
        counter dd ?
        i dd ?
        currentNumber dd 11 dup(?)
        currentNumberOfDigits dd ?
        j dd ?
        numberOfPermutations dd ?


    section '.idata' data readable import
        library msvcrt,'msvcrt.dll'
            import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
AsmEnd

The 32-bit Windows executable is available here, it's called permutations.exe.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Why assembly? These days it's not a common choice. \$\endgroup\$
    – Reinderien
    Apr 29, 2020 at 13:29
  • \$\begingroup\$ @Reinderien, Assembly is used to call C functions "printf" and "scanf". The algorithm is written in AEC. I thought it was obvious. \$\endgroup\$ Apr 29, 2020 at 13:59

1 Answer 1

2
\$\begingroup\$

Coding style

numberOfDigits:=0
numberOfDigits := numberOfDigits + 1
countDigits[i] := 0
countDigits [lastDigit] := countDigits (lastDigit) + 1
myStack [ (numberOfDigits + 1) ] := 0
myStack (topOfMyStack * (numberOfDigits + 1) ) := currentNumberOfDigits + 1

Throughout the program your use of whitespace and brackets is inconsistent.
Even if you have the choice between [] and () to address array elements, you should choose one of them and stick with your choice.
This fickleness is especially annoying in countDigits [lastDigit] := countDigits (lastDigit) + 1

Alternative

You can remove the high level subscript:=4*i if you use a scaled address form:

 i:=0
 While i<10
   AsmStart
     fld   dword [i]
     fistp dword [subscript]
     mov   ebx, [subscript]
     pushIntegerToTheSystemStack (countDigits + ebx * 4)
     ...

Warning

It's nice that you prompt the user for a non-zero number but your program should actually verify this.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.