Reputation: 313
I think I'm having trouble with my swap, and how I'm accessing the elements in my array. Right now, all of the code runs, but the list does not change after the sort. He's the high level sort I'm trying to implement
for(k=0; k<request-1; k++) {
i = k;
for(j=k+1; j<request; j++) {
if(array[j] > array[i])
i = j;
}
exchange(array[k], array[i]);
}
Here's the assembly code. Note: the assignment is about pushing and popping elements on/off the stack, so I can't change the parameters.
;this is a library with macros for things like printing numbers and strings
INCLUDE Irvine32.inc
MIN = 10 ;lower range limit
MAX = 200 ;upper range limit
LRANGE = 100
HRANGE = 999
.data
;title, intro, and prompts
title_1 BYTE "PROGRAMMING ASSIGNMENT 5: RANDOM GEN/SORT", 0dh, 0ah, 0
intro_1 BYTE "This program generates random numbers in the range (100 - 999),", 0dh, 0ah
BYTE "displays the original list, sorts the list, and calculates the median value.", 0dh, 0ah
BYTE "Finally, it displays the sorted list in descending order.", 0dh, 0ah, 0
prompt_1 BYTE "How many numbers should be generated? (10 - 200): ", 0
error_1 BYTE "Out of range.", 0dh, 0ah, 0
display_1 BYTE "List of random numbers: ", 0dh, 0ah, 0
display_2 BYTE "The median is: ", 0
display_3 BYTE "The sorted list: ", 0dh, 0ah, 0
;placeholders for user entries and calculated data
randArray DWORD MAX DUP(?)
userNum DWORD ? ;integer to be entered by user
;strings for posting results
goodBye_1 BYTE "Thank you for using the Gen/sort-ulator! Good-bye!", 0
.code
main PROC
call Randomize
;Title Screen
push OFFSET title_1
push OFFSET intro_1
call Intro
;Get and validate user numbers
push OFFSET error_1
push OFFSET prompt_1
push OFFSET userNum
call GetData
;Fill Array with random numbers
push OFFSET randArray
push userNum
call FillArray
;display unsorted results
push OFFSET randArray
push userNum
push OFFSET display_1
call DisplayList
;sort the results
push OFFSET randArray
push userNum
call SortList
;display the median
push OFFSET randArray
push userNum
push OFFSET display_2
call median
;display sorted results
push OFFSET randArray
push userNum
push OFFSET display_3
call DisplayList
;Say "goodbye"
push OFFSET goodBye_1
call Goodbye
exit ; exit to operating system
main ENDP
;-------------------------------------------------------
;Gives an Intro to the program
; Receives parameters on the system stack (in the order pushed):
; Address of the title
; Address of the intro
;post: intro displayed
;registers: none
;-------------------------------------------------------
Intro PROC
pushad
mov ebp, esp
mov edx, [ebp+40]
call writeString
call CrLf
mov edx, [ebp+36]
call writeString
call CrLf
popad
ret 8
Intro ENDP
;-------------------------------------------------------
;Prompts user for an integer, int stores in userNum
; Receives parameters on the system stack (in the order pushed):
; Address of the error message
; Address of the prompt
; Address of return value
;Post: userNum
;registers: none
;-------------------------------------------------------
GetData PROC
pushad
;setup stack and prompt for entry
mov ebp, esp
reenter:
mov edx, [ebp+40]
mov ebx, [ebp+36]
call WriteString
call ReadInt
;validate entry
cmp eax, MIN ;if eax < LOWER
jl badEntry ;jump to summary
cmp eax, MAX ;if eax > UPPER
jg badEntry ;reprompt
jmp goodEntry ;else jump to end, we have a good value
;bad entry reprompt
badEntry:
mov edx, [ebp+44]
call WriteString
jmp reenter
goodEntry:
call CrLf
mov [ebx], eax
popad
ret 12
GetData ENDP
;-------------------------------------------------------
;Fills array with a number of random integers within RANGE
;Recieves parameters on the system stack (in order pushed)
; array
; userNum
;Post: array is filled with userNum number of randoms
;Registers used: none
;-------------------------------------------------------
FillArray PROC
pushad
mov ebp, esp
mov ecx, [ebp+36] ;initialize loop counter with user entry
mov edi, [ebp+40] ;setup array offset
fillLoop:
call nextRand
add edi, 4
loop fillLoop
popad
ret 8
FillArray ENDP
;-------------------------------------------------------
; Procedure nextRand
; adapted from check lecture 20 solutions
; Procedure to get the next random number in the range specified by the user.
; Preconditions: LRANGE < HRANGE
; Registers used: eax, edi
;-------------------------------------------------------
nextRand PROC
mov eax, HRANGE
sub eax, LRANGE
inc eax ;add 1 to get the number of integers in range
call RandomRange
add eax, LRANGE ;eax has value in [LOW - HIGH]
mov [edi],eax
ret
nextRand ENDP
;-------------------------------------------------------
;Sorts the contents of an integer array
; Receives parameters on the system stack (in order pushed)
; Array
; Array Size
;registers: none
;-------------------------------------------------------
sortList PROC
pushad
mov ebp, esp
mov ecx, [ebp+36]
mov edi, [ebp+40]
dec ecx ;ecx < request-1
mov ebx, 0 ;ebx=k
;for(k=0; k<request-1; k++)
outerLoop:
mov eax, ebx ;eax=i=k
mov edx, eax
inc edx ;edx=j=k+1
push ecx
mov ecx, [ebp+36] ;ecx < request
;for(j=k+1; j<request; j++)
innerLoop:
mov esi, [edi+edx*4]
cmp esi, [edi+eax*4]
jle skip
mov eax, edx
skip:
inc edx
loop innerLoop
;swap elements
lea esi, [edi+ebx*4]
push esi
lea esi, [edi+eax*4]
push esi
call exchange
pop ecx
inc ebx
loop outerLoop
popad
ret 8
sortList ENDP
;-------------------------------------------------------
; Exchange k and i
; Receives parameters on the system stack (in order pushed)
; array[k]
; array[i]
;registers: none
;-------------------------------------------------------
Exchange PROC
pushad
mov ebp,esp
mov eax, [ebp+40] ;array[k] low number
mov ecx, [eax]
mov ebx, [ebp+36] ;array[i] high number
mov edx, [ebx]
mov [eax], edx
mov [ebx], ecx
popad
ret 8
Exchange ENDP
;-------------------------------------------------------
;Displays the median of an integer array
; Receives parameters on the system stack (in order pushed)
; Array
; Array Size
; display string
;registers: none
;-------------------------------------------------------
Median PROC
pushad
mov ebp, esp
mov edi, [ebp+44]
;display string
mov edx, [ebp+36]
call writeString
;calculate median element
mov eax, [ebp+40]
cdq
mov ebx, 2
div ebx
shl eax, 2
add edi, eax
cmp edx, 0
je isEven
;Array size is odd, so display the middle value
mov eax, [edi]
call writeDec
call CrLf
call CrLf
jmp endMedian
isEven:
;Array size is even so average the two middle values
mov eax, [edi]
add eax, [edi-4]
cdq
mov ebx, 2
div ebx
call WriteDec
call CrLf
call CrLf
endMedian:
popad
ret 12
Median ENDP
;-------------------------------------------------------
;Displays the contents of an integer array, 10 per row
; Receives parameters on the system stack (in order pushed)
; Array
; Array Size
; display string
;registers: none
;-------------------------------------------------------
DisplayList PROC
pushad
mov ebp, esp
;display string
mov edx, [ebp+36]
call writeString
call CrLf
mov ecx, [ebp+40]
mov edi, [ebp+44]
mov ebx, 0
;display array contents
listloop:
inc ebx ;counter for 10 items per row
mov eax, [edi]
call writeDec
add edi, 4
cmp ebx, 10
jne noReturn ;jump if 10 items are not yet printed
call CrLf
mov ebx, 0
jmp noTab ;this skips adding a tab on a new row
noReturn:
mov al, TAB
call writeChar
noTab:
loop listloop
call CrLf
popad
ret 12
DisplayList ENDP
;-------------------------------------------------------
;Says good-bye to the user
; Receives parameters on the system stack:
; Address of string
;registers: none
;-------------------------------------------------------
Goodbye PROC
pushad
mov ebp, esp
mov edx, [ebp+36]
call writeString
call CrLf
popad
ret 4
Goodbye ENDP
END main
Upvotes: 2
Views: 6960
Reputation: 58762
In order to exchange elements you should be passing their address (in other words, a pointer to each). What you did was just swapping the values passed as parameters, which were also immediately freed. Your code is the equivalent of this C function:
void Exchange(int x, int y)
{
int eax = x;
int ebx = y;
x = ebx;
y = eax;
}
You need something like:
void Exchange(int* x, int* y)
{
int eax = *x;
int ebx = *y;
*x = ebx;
*y = eax;
}
In asm, that may look like:
Exchange PROC
pushad
mov eax, [esp+40]
mov ecx, [eax]
mov ebx, [esp+36]
mov edx, [ebx]
mov [eax], edx
mov [ebx], ecx
popad
ret 8
Exchange ENDP
To call this function you would use the following:
lea esi, [edi+ebx*4]
push esi
lea esi, [edi+eax*4]
push esi
call Exchange
Note your Exchange
function had an instruction mov eax, [edi]
which I couldn't make sense of.
Update: Yes, you can emulate the functionality of LEA
by doing the calculations manually. For example, lea esi, [edi+ebx*4]
becomes:
mov esi, ebx
shl esi, 2 ; esi=ebx*4
add esi, edi ; esi=edi+ebx*4
Upvotes: 2