Sorting an array from biggest to least in Assembly language x86 - arrays

I'm trying to sort an array using the registers from biggest to least and nothing seems to be working. The ecx is my amount of numbers that I have, the esi is the address of my list which consists of dwords. I use the edx to keep going up by 4 bytes to each element. My code doesn't sort the entire array I know that I need to find the location of the max and then set it equal to the outer loops edx but I can't seem to figure out how to change the elements in the array because I only have the edx register. I tried pushing the location and then popping it back out when the inner loop was finished but that didn't seem to work. Please anything is appreciated I have been working on this problem for over 4 hours.
push ebp
mov ebp,esp
mov ecx,[ebp+8]
mov esi,[ebp+12]
mov edx,-4
outerloop:
add edx,4
push edx
push ecx
mov ebx,[edx+esi]
innerloop:
add edx,4
mov eax,[edx+esi]
cmp ebx,eax
jl change
finish:
loop innerloop
pop ecx
pop edx
loop outerloop
jmp done
change:
mov [edx+esi],ebx
mov [edx+esi-4],eax
sub edx,4
push edx
mov edx,offset change1
call writestring
pop edx
jmp finish
done:
pop ebp
ret 8

What you are looking for is a 'reversed' Bubble Sort (You can of course use any sorting algorithm you wish, but this is simple for an example). I'm not sure what assembler you're using, but here's a short assembly function that will accomplish a sort of n int32_t integers stored in array/list arr. (This example was written in NASM)
;int *sort(int *arr,int n);
sort:
push ebp
mov ebp,esp
mov edx,[ebp+12]
.loop1:
mov esi,[ebp+8] ;arr ptr
mov ecx,[ebp+12] ;n number of ints
.loop2:
mov eax,[esi] ;compare
mov ebx,[esi+4]
cmp eax,ebx
jg .skip
mov [esi],ebx ;swap
mov [esi+4],eax
.skip:
add esi,4 ;perform loop checks
dec ecx
cmp ecx,1
ja .loop2
dec edx
ja .loop1
mov eax,[ebp+8] ;return arr
mov esp,ebp
pop ebp
ret
Please keep in mind this example wasn't really optimized (e.g., it iterates too many times through the whole array). Sometimes (esp. in assembly languages), less is more. Instead of offsetting the pointer by ecx/edx, you can increment the array pointer (or a copy of it), and do comparisons using that directly. This way you don't have to keep track of a counter register AND the pointer at the same time. :)

Related

How to sort an array using stack in assembly

I want to sort an array while using the stack:
so first things first I pushed it all into the stack.
then I'm locating the minimum element in the stack, swapping it with the top element popping it out and move it back to the array.
but something isn't right and about halfway there it got messed up (DI is one index below than what it should really be)
data segment
a db 5h,12h,6h,4h,9h
len equ $-a
loop_counter db len
min_index dw 0
min db ?
ends
stack segment
dw 128 dup(0)
ends
code segment ;TODO: Locate min in stack xchg it with top element copy to array and pop it :|
start:
mov ax, data
mov ds, ax
mov bx,0
mov cx,0
mov cl,loop_counter
push_arr_to_stack:
mov al,a[bx]
push ax
inc bx
loop push_arr_to_stack
mov bx,len-1
mov ax,0
mov cl,loop_counter
mov bp,sp
mov ax,[bp]
mov bx,[bp]
mov di,0
mov dx,0
mov si,2
mov di_check,len-loop_counter
find_min_to_arr:
cmp bx,ax
jb new_min
mov bx,[bp+si]
add si,2
loop find_min_to_arr
mov min,al
xchg a[di],al
jmp pop_min
new_min:
mov ax,bx
mov bx,[bp+si]
mov min_index,si
sub min_index,2
add si,2
dec cx
jmp find_min_to_arr
pop_min:
mov dx,[bp]
xchg di,min_index
mov [bp+di],dx
xchg di,min_index
pop dx
mov dx,0
inc di
mov si,0
cmp di,len
je b
dec loop_counter
mov cl,loop_counter
jmp find_min_to_arr
b:
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start
first I pushed it all into the stack.
This part is fine although for speed reasons you should forget about loop .. and replace it with dec cx followed by jnz ..
then I'm locating the minimum element in the stack, swapping it with the top element popping it out and move it back to the array.
Here your code gets very complicated and it contains many errors. Also the code does not perform true swapping between the located minimum and the element at the top of the stack.
I tried amending your code but as is often the case, it is beyond repair. Below is my rewrite that you should study, not just copy!
I have defined the loop_counter a word variable because that's easier. Additionally I kept it in the DX register that was sitting there doing nothing...
Pushing it all into the stack
mov bx, dx
push_arr_to_stack:
mov al, a[bx-1]
push ax
dec bx
jnz push_arr_to_stack
I push the array in reverse so the stack has the elements in the same order as the original array. This is not necessary for the task, but it is simpler and it leaves the BX register at zero for use below.
Locating the minimum in the stack
Again:
mov bp, sp
xor si, si
mov al, [bp+si] ; Chosen minimum
mov di, si ; Remember its position
mov cx, dx
dec cx ; N elements = N-1 compares
jz .c
.a: add si, 2
cmp al, [bp+si]
jbe .b
mov al, [bp+si] ; New minimum
mov di, si ; Remember its position
.b: dec cx
jnz .a
Swapping it with the top element
.c: xchg al, [bp]
mov [bp+di], al
Popping it out and moving it back to the array
pop ax
mov a[bx], al
inc bx
dec dx
jnz Again
The important thing here is that the above exactly does what the task description said.

MASM x86 How to sort an array in ascending order?

I have managed to successfully sort my array in descending order, but I'm a bit confused about how to sort it into ascending order as well.
I basically want to sort my array into ascending order as well, but I'm kind of stuck. I don't know if I'm overthinking it or not, but I've run into a big roadblock for such a simple problem.
Here's what I have coded for sorting my array of random numbers into descending order:
"""
sortList PROC
push ebp
mov ebp, esp
mov ecx, [ebp + 8]
mov esi, [ebp + 12]
dec ecx
outer_loop:
mov eax, [esi]
mov edx, esi
push ecx
inner_loop:
mov ebx, [esi + 4]
mov eax, [edx]
cmp eax, ebx
jge do_not_swap
;Else, push parameters and swap
add esi, 4
push esi
push edx
push ecx
call exchange
sub esi, 4
do_not_swap:
add esi, 4
loop inner_loop
;End the inner loop and restore outer loop stuff
pop ecx
mov esi, edx
add esi, 4
loop outer_loop
pop ebp
ret 8
sortList ENDP
"""
Any help is greatly appreciated!
Thanks so much for your time.
jge do_not_swap
The jge instruction means JumpIfGreaterOrEqual.
Reversing the sort order is a simple matter of using jle which stands for JumpIfLessOrEqual. That is if the rest of the code works fine like you're saying...
A 1 character change, what great value for your money!

Sorting array in x86 assembly language

I have to sort an array in descending order using parameters on the stack to an array and an array size. I passed the size by value at ebp+12 and the array by reference at ebp+8.
I know the code is kind of all over the place, but I'm just trying to get to something that works and I can try to clean it up from there.
I've been debugging and it seems to iterate through as I want it to, but my array isn't being sorted. I've been banging my head against this for hours, so any guidance would be greatly appreciated.
The pseudo-code algorithm I'm trying to follow is:
for(k=0, k<arrlength-1,k++)
I=K
for(J=k+1,J<arrlength,J++)
if(arr[j]>arr[i])
I=J
xchg(arr[k], arr[i])
And this is my attempt to implement it in x86 assembly:
;------------------------------------------------
sortlist PROC
;Sorts an array of specified size into descending order
;Receives: DWORD request value, address of an array
;Returns: array of size request, sorted in descending order
;------------------------------------------------
.data
first DWORD ?
next DWORD ?
.code
push ebp
mov ebp, esp
mov ecx, [ebp+12]
mov edi, [ebp+8]
mov eax, 0
mov ebx, 0
mov edx, 0
mov esi, 0
dec ecx ;loop for array length - 1
L1:
add edi, ebx ;ebx = 0 first loop, 4 all remaining loops
mov eax, [edi] ;get the value of the first element
mov first, edi ;store address of first element in first
mov next, edi
push ecx
push edi
L2:
add edi, 4 ;move to next element in array
mov edx, [edi] ;set value of next element to edx
cmp [next], edx ;compare element to next element
jg nxt
mov next, edi ;If less than, move address of greater to next
nxt:
loop L2
mov eax,[next] ;move values pointed to by 1st & next to regs
mov ebx,[first]
mov [first],eax ;move values(swapped) to addresses
mov [next],ebx
mov ebx,4
pop edi
pop ecx
loop L1
pop ebp
ret 8
sortlist ENDP

I am dealing with a possible array in assembly, but I cannot figure out what the starter value is

Size contains the number 86.
var_10= dword ptr -10h
var_C= dword ptr -0Ch
size= dword ptr 8
push ebp
mov ebp, esp
sub esp, 28h
mov eax, [ebp+size]
mov [esp], eax ; size
call _malloc
mov ds:x, eax
mov [ebp+var_C], 0
jmp short loc_804889E
loc_804889E: ~~~~~~~~~~~~~~~~~~~~~
mov eax, [ebp+size]
sub eax, 1
cmp eax, [ebp+var_C]
jg short loc_8048887
loc_8048887: ~~~~~~~~~~~~~~~~~~~~~
mov edx, ds:x
mov eax, [ebp+var_C]
add edx, eax
mov eax, [ebp+var_C]
add eax, 16h
mov [edx], al
add [ebp+var_C], 1
I am having difficulties reversing this portion of a project I am working on. There's a portion of the code where ds:x is moved into edx and is added with var_c and I am unsure where to go with that.
To me the program looks like it calls malloc and then moves that into ds:x and then moves 0 to var_c.
After that it simply subtracts 1 from the size of my pointer array and compares that number to 0, then jumps to a portion where it adds ds:x into edx so it can add eax to edx.
Am I dealing with some sort of array here? What is the first value that's going to go into edx in loc_8048887? Another way this could help would be to see a C equivalent of it... But that would be what I am trying to accomplish and would rather learn the solution through a different means.
Thank you!
In x86 assembly there's no strict distinction between a variable stored in memory and an array in memory. It only depends on how you access the memory region. All you have is code and data. Anyway, I'd say that ds:x is an array as because of this code here:
mov edx, ds:x ; edx = [x]
mov eax, [ebp+var_C] ; eax = something
add edx, eax ; edx = [x] + something
mov eax, [ebp+var_C] ; eax = something
add eax, 16h ; eax = something + 0x16
mov [edx], al ; [[x] + something ] = al . Yes, ds:x is an array!
What is the value of edx in loc_8048887? To find it out you only need some very basic debugging skills. I assume you have gdb at hand, if not, get it ASAP. Then compile the code with debug symbols and link it, then run gdb with the executable, set a code breakpoint at loc_8048887, run the program with r, and finally check the value of edx.
These are the commands you need:
gdb myexecutable
(gdb) b loc_8048887
(gdb) r
(gdb) info registers edx

memory corrupt using assembler procedure

I've written this procedure in asm:
.586
.model flat, stdcall
.xmm
.data
.code
EncryptAsm proc plainText:ptr byte, heigth:DWORD, inputLength:DWORD, encryptedText:ptr byte, cipherArray:ptr byte
local addRow:WORD
local row:DWORD
local column:DWORD
local iterator:DWORD
local forLoopIteratorI:DWORD
local forLoopIteratorJ:DWORD
push esi
push edi
push ebx
push ecx
push edx
mov addRow,0
mov row,0
mov column,0
mov iterator,0
mov forLoopIteratorI,0
mov forLoopIteratorJ,0
mov ecx,heigth
FILL_CIPHER_ARRAY_LOOP: mov eax, inputLength
cmp iterator,eax
jge PREPARE_ITERATOR
push ecx ;pushing heigth value
mov ecx,row ;calculating index of cipher array index=[row*inputLength+column]
imul ecx,inputLength
add ecx,column
mov eax,iterator
mov edx,plainText
mov al,[edx+eax]
mov [esi],al
mov ebx, cipherArray
mov [ebx+ecx],al
movsb
pop ecx;getting back heigth value
add column,1
cmp addRow,0
je INC_ROW
cmp addRow,0
jne DEC_ROW
INC_ROW: add row,1
jmp ROW_COMPARE
DEC_ROW: sub row,1
jmp ROW_COMPARE
ROW_COMPARE: cmp row,ecx
jge IF_STATEMENT_1
cmp row,0
jl IF_STATEMENT_2
jmp INCREMENT_ITERATOR
IF_STATEMENT_1: sub row,2
mov addRow,1
jmp INCREMENT_ITERATOR
IF_STATEMENT_2: add row,2
mov addRow,0
jmp INCREMENT_ITERATOR
INCREMENT_ITERATOR: add iterator,1
jmp FILL_CIPHER_ARRAY_LOOP
PREPARE_ITERATOR: mov iterator,0
READ_CIPHER_ARRY_LOOP_I:cmp forLoopIteratorI,ecx
jge PREPARE_ITERATOR_2
READ_CIPHER_ARRY_LOOP_J:mov eax, inputLength
cmp forLoopIteratorJ,eax
jge PREPARE_I_AND_J
push ecx ;pushing heigth value
mov ecx,forLoopIteratorI ;calculating index of cipher array
imul ecx,inputLength
add ecx,forLoopIteratorJ
mov ebx,cipherArray
mov al,[ebx+ecx]
cmp al,'#'
jne COPY_VALUE
ITERATE: add forLoopIteratorJ,1
pop ecx
jmp READ_CIPHER_ARRY_LOOP_J
PREPARE_I_AND_J: mov forLoopIteratorJ,0
add forLoopIteratorI,1
jmp READ_CIPHER_ARRY_LOOP_I
COPY_VALUE: push edi
mov edi,iterator
mov edx,encryptedText
mov [edx+edi],al
add iterator,1
pop edi
jmp ITERATE
PREPARE_ITERATOR_2: mov iterator,0
FINISH: mov eax, encryptedText
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
EncryptAsm endp
end
It implements rail fence cipher algorithm (at the end the variable encryptedText contains ciphered plainText). It works fine, I mean it does the encryption well but after all I'm getting memory corrupt error... I'm calling this procedure as an extern one from C app. I can print the encrypted text without any problem but when returning 0 in main function, the memory corrupt error pops up.
I don't know what can cause it. At the beginning of asm procedure, I push all the registers' values and pop them after the whole operation.
The error message:
Unhandled exception at 0x72676F74 in ConsoleApplication12.exe: 0xC0000005: Access violation executing location 0x72676F74.
I'll be greatful for any hint.
One possible candidate could be here:
mov edx,plainText
mov al,[edx+eax]
mov [esi],al
esi is pushed, from the caller, but where is it initialized? It seems that it uses whatever is there from the caller. Same for edi so where will movsb store it?
UPDATE
Since I don't know your algorithm and don't see how it is used I can only guess. BUt I think you should do the following before the loop:
mov esi, plainText
mov edi, encryptedText
mov ebx, cipherArray
Since you don't change these values you can then change this code:
COPY_VALUE: push edi
mov edi,iterator
mov edx,encryptedText
mov [edx+edi],al
add iterator,1
pop edi
jmp ITERATE
to this:
COPY_VALUE: mov edx,iterator
mov [edx+edi],al
inc iterator
jmp ITERATE
Generally instead of using add x, 1 you can use inc x which is shorter.
People I've found it! The cause of the error was... 'movsb'. I was using it in a previous version of my algorithm and I've forgotten to delete it... The rest of my code works fine. Thanks for all the answers and for willing to help m ;)

Resources