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.

asked Apr 29, 2020 at 10:48
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Why assembly? These days it's not a common choice. \$\endgroup\$ Commented 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\$ Commented 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.

answered May 10, 2020 at 20:26
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.