你如何在MASM Assembly中进行选择排序?

时间:2014-03-17 03:16:26

标签: sorting assembly x86 masm irvine32

所以我试图按升序对数组进行排序,它似乎对我不起作用。我知道我的交换过程是错误的,我的minIndex程序只能工作一半,但随机填充的数组生成就好了。

工作代码感谢vitsoft:

include Irvine32.inc

; Constants
    NUM_INTEGERS = 20
    NUM_RANGE = 99d
    TO_ENSURE_NOT_ZERO = 1d

.data
; Declare Arrays
; Declare Array of 20 Integers
    array byte NUM_INTEGERS dup(?)

; Displayed Annotation for Unsorted Array
    unsortedArrayText byte "Randomly Generated Array, Unsorted: ", 0dh, 0ah, 0

; Displayed Annotation for Sorted Array
    sortedArrayText byte "Randomly Generated Array, Sorted from Lowest to Highest: ", 0dh, 0ah, 0

.code
main PROC
; Get Random Values for Array
    call fillArrayRandomly

; Display Array with Annotation
    mov edx, offset unsortedArrayText
    call WriteString

    mov ecx, offset array
    push ecx
    call displayArray

; Sort Array
    mov esi, offset array
    mov ecx, NUM_INTEGERS
    call findMinimum

    mov edi, offset array
    mov ecx, NUM_INTEGERS
    call selectionSort

; Display Sorted Array with Annotation
    mov edx, offset sortedArrayText
    call WriteString

    mov ecx, offset array
    push ecx
    call displayArray

; Exit Program
    exit
main endp

; Fill Array with Random Values
fillArrayRandomly PROC
; Set Counter to NUM_INTEGERS and Index to 0
    mov eax, 0
    mov ecx, NUM_INTEGERS
    mov esi, 0

getRandomNumber:
; Fill Array with Random Numbers and Increment ESI for Offset
    mov ah, NUM_RANGE
    call RandomRange
    add ah, TO_ENSURE_NOT_ZERO

testUniqueness:
    mov al, array [esi]
    cmp al, ah
    jne uniqueNumber
    loop getRandomNumber

uniqueNumber:
    mov array [esi], ah
    inc esi
    loop getRandomNumber

    ret
fillArrayRandomly ENDP

; Display Array
displayArray PROC
    pushad
    mov eax, 0
    mov ecx, NUM_INTEGERS
    mov esi, 0

display:
    mov al, array[esi]
    call WriteDec
    mov al, TAB
    call WriteChar
    inc esi
    loop display

    popad
    call Crlf
    ret
displayArray ENDP

; Selection Sort
selectionSort PROC
    dec ecx
    mov ebx, edi
    mov edx, ecx

startOuterLoop:
    mov edi, ebx
    mov esi, edi
    inc esi
    push ecx
    mov ecx, edx

startInnerLoop:
    mov al, [esi]
    cmp al, [edi]
    pushf
    inc esi
    inc edi
    popf
    jae doNotSwap
    call swap

doNotSwap:
    loop startInnerLoop
    pop ecx
    loop startOuterLoop

    ret
selectionSort ENDP

; Find Minimum Index
findMinimum PROC
    mov edi, esi

minimumIndex:
    mov al, [esi]
    cmp al, [edi]
    jae skip
    mov edi, esi

skip: 
    inc esi
    loop minimumIndex

    ret
findMinimum ENDP

; Swap
swap PROC
    mov al, [esi - 1]
    mov ah, [edi - 1]
    mov [esi - 1], ah
    mov [edi - 1], al

    ret
swap ENDP

END main

2 个答案:

答案 0 :(得分:1)

LOAD EFFECTIVE ADDRESS计算第二个操作数的地址并将其移动到第一个操作数。

lea esi,[edi + 1] 可以替换为

mov esi,edi
inc esi 

如果您不介意INC也会改变ZERO标志。

你应该尽快学习 cmpsb 和其他字符串指令,它们非常有用。

cmpsb 可以替换为

MOV AL,[ESI]
CMP AL,[EDI]
PUSHF
 INC ESI
 INC EDI 
POPF

在调用 selectionSort 之后,最小值将位于数组的第一个字段中。 不过,如果你的任务是找到一个指向数组最小值的指针,那么你就是:

findMinimum PROC ; Return EDI=offset of leftmost byte in array with minimal value
; Input: ESI is offset of an byte array,  ECX is the size of array
      MOV EDI,ESI  ; Initialize pointer with so far minimal value
 next:MOV AL,[ESI] ; Load next value
      CMP AL,[EDI] ; Compare with minimal value so far 
      JAE skip
      MOV EDI,ESI  ; Value loaded from [ESI] was below, so ESI is better candidate
 skip:INC ESI      ; Advance offset in array
      LOOP next
      RET
findMinimum ENDP

答案 1 :(得分:0)

.data
unsortedArrayText DB "Randomly Generated Array, Unsorted: ", 0dh, 0ah, 0
sortedArrayText   DB "Randomly Generated Array, Sorted from Lowest to Highest: ", 0dh, 0ah, 0 
array             DB "An array of bytes (characters) which will be sorted"
NewLine           DB 0dh, 0ah, 0
NUM_INTEGERS      EQU NewLine - array ; Number of integers (characters) in array  
.code

main PROC
; Display Array with Annotation
; mov edx, offset unsortedArrayText
; call WriteString
ConsoleWrite unsortedArrayText
  ; push offset array
  ; call displayArray
ConsoleWrite array

; Sort Array
  ;   push offset array
  ;   call selectionSort
MOV EDI,array
MOV ECX,NUM_INTEGERS
CALL selectionSort

; Display Sorted Array with Annotation
   ; mov edx, offset sortedArrayText
   ; call WriteString
ConsoleWrite sortedArrayText
   ; push offset array
   ; call displayArray
ConsoleWrite array
; Exit Program
    ;exit
 TerminateProgram
main endp

; Selection Sort
selectionSort PROC ; Bubble sort ECX byte array pointed to with EDI
    DEC ECX        ; Number of compare is NUM_INTEGERS-1
    MOV EBX,EDI    ; Save array pointer to EBX
    MOV EDX,ECX    ; Save number of compare to EDX
OuterLoop:
    MOV EDI,EBX    ; Restore array pointer     
    LEA ESI,[EDI+1] ; Neibourghing field
    PUSH ECX        ; Save OuterLoop counter on stack
     MOV ECX,EDX     ; Initialize InnerLoop counter
InnerLoop:    
     CMPSB ; compare the first byte [EDI] with its neibourgh [ESI], advance EDI,ESI
     JAE NoSwap
     CALL swap
NoSwap:
     LOOP InnerLoop
    POP ECX     ; Restore OuterLoop counter
    LOOP OuterLoop
    RET
selectionSort ENDP

swap PROC ; Swap bytes at [EDI-1] and [ESI-1]
     MOV AL,[ESI-1]
     MOV AH,[EDI-1]
     MOV [ESI-1],AH
     MOV [EDI-1],AL
     RET
swap ENDP

这很好用,静态定义的数组在几毫秒内排序:

C:\ASM>bubblesortexample.exe
Randomly Generated Array, Unsorted:
An array of bytes (characters) which will be sorted
Randomly Generated Array, Sorted from Lowest to Highest:
        ()Aaaaabbcccdeeeefhhhiillnoorrrrrssstttwwyy
C:\ASM>