beginner in assembly here (IA-32 assembly). I keep getting a seg fault when compiling in gcc, I'm guessing its attempting to access forbidden memory, but I can't pin point it down. The task was to find the greatest common denominator of an array. I figured implementing this via an array with a side function gcd (returns the gcd of 2 numbers). Here is the code:
.intel_syntax noprefix
.text
.global GCD
GCD:
push edi
push esi
mov edi, [ebp + 12] # number of elements in the array
mov esi, [ebp + 8] #array address
mov eax, [esi] # place the first element of the array into eax
mov ecx, 1 # set the counter to 1
next_number: #accumulating the gcd of the entire array
cmp ecx, edi #if the counter reaches the max number of elements,
ja end #end the the loop
push [esi + 4*ecx] #calling the gcd function, pushing the numbers on the
push eax #stack, so gcd can pick them up
call gcd
add esp, 8
inc ecx #increment the counter
jmp next_number #next iteration
end:
pop esi
pop edi
leave
ret
And the gcd side function:
# The C algorithm for finding the gcd of 2 numbers implemented in IA-32
# while(y)
# {
# r = x % y;
# x = y;
# y = r;
# }
# return x;
.intel_syntax noprefix
.text
.global gcd
gcd:
enter 0,0
mov eax, [ebp + 8]
mov ecx, [ebp + 12]
loop:
cmp ecx, 0
je end
xor edx, edx
idiv ecx
mov eax, ecx
mov ecx, edx
jmp loop
end:
leave
ret
Related
Today I'm working on arrays and addressing modes so I made this snippet to train myself. Everything is working fine (apparently) but I chose the easiest way using fixed size arrays. My question is about dynamic memory allocation. In my code, my arrays arrayand array2 have a fixed size (8 * 4(int)). If I wanted to extend them, or to speak with C concepts, make a realloc or something like depending on real time values for the size, may I have to implement system calls like sys_brk and mmapby myself in assembly
or is there an other option ? The other question deals with the part of my code used to reverse an array (label .reversing) I know they are faster solutions than mine so if you could give me some advices, it would be nice.
%define ARRAY_LEN 8
%macro print 2
mov eax, 4
mov ebx, 1
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
%macro exit 0
xor ebx, ebx
mov eax, 1
int 0x80
%endmacro
section .bss
sumarrays resd 1
dynarray resd 256
section .rodata
highest equ 0x78
evensum equ 0x102
sumarray1 equ 0x1e6
sumarray2 equ 0x256
section .data
revarray times ARRAY_LEN dd 0
strok db "Good result !", 0xa, 0
lenstrok equ $ - strok
strerror db "Bad result !", 0xa, 0
lenerror equ $ - strerror
array dd 0x33, 0x21, 0x32, 0x78, 0x48, 0x77, 0x19, 0x10
array2 dd 0x12, 0x98, 0x65, 0x62, 0x4e, 0x3e, 0x1f, 0x3a
section .text
global sort
global sum
global _start
_start:
; sort array from highest value to lowest value
sub esp, 8
push ARRAY_LEN
push array
call sort
add esp, 8
and esp, 0xfffffff0
; copying array into some another ones : array -> revarray
mov esi, eax
mov edi, revarray
mov ecx, ARRAY_LEN
rep movsd
; now let's reverse the array
mov esi, revarray ;esi = address of array
mov ecx, ARRAY_LEN ;ecx = number of elements
lea edi, [esi + ecx * 4 - 4]
.reversing:
mov eax, [esi] ;eax = value at start
mov ebx, [edi] ;ebx = value at end
mov [edi], eax
mov [esi], ebx
add esi, 4 ;incrementing address of next item at start
sub edi, 4 ;incrementing address of next item at end
cmp esi, edi ;middle reached ?
jb .reversing ;no we continue
.reversed:
;after, we compute the sum of the elements in the array
mov esi, revarray ; address of array
mov edx, ARRAY_LEN ; num elem of array
sub esp, 8
call arraysum ; sum computation
add esp, 8
cmp eax, sumarray1 ; we check the result to be sure
jne .failure
; merging array2 with array
; esi = source address of first array
; edi = address of second array, the destination one
mov esi, array2
mov edi, array
sub esp, 8
call mergearrays
add esp, 8
; we compute the sum of the merged arrays into the new (old one in fact)
mov esi, array
mov ecx, ARRAY_LEN
add esp, 8
call arraysum
add esp, 8
cmp eax, 0x43c ; we check the result to be sure
jne .failure ; if not egal, exit
; compute the sum of even numbers only in the array
; set up edx to 0 at beginning of loop
; cmova edx, $value_even_number
mov esi, revarray
xor ebx, ebx
xor ecx, ecx
.iterate:
xor edx, edx ; setting up edx to 0
mov eax, [esi + ecx * 4]
test al, 1 ; CF == 0 ? so it's an even number
cmovz edx, eax ; we store the value of current element in edx
add ebx, edx ; so in case of odd number => add 0
inc ecx
cmp ecx, ARRAY_LEN ; end of array reached ?
jne .iterate ; no, we continue
cmp ebx, 0x102 ; check if result is good
je .success
jmp .failure
exit
.success:
print strok, lenstrok
exit
.failure:
print strerror, lenerror
exit
; ********************************************
; computes the sum of all elements of an array
; esi = address of the array
; edx = number of elements in array
; output : eax
; ********************************************
arraysum:
push ebx
xor ebx, ebx
xor ecx, ecx
.arraysum:
mov eax, [esi + ecx *4]
add ebx, eax
inc ecx
cmp ecx, edx
je .sumdone
jmp .arraysum
.sumdone:
mov eax, ebx
pop ebx
ret
; *********************************************
; procedure that sort array from highest to lowest value
; first arg = address of the array
; second arg = number of elements in a array
; return : eax, sorted array
; ********************************************
sort:
push ebp
mov ebp, esp
mov edx, [ebp + 12]
.loop1:
mov esi, [ebp + 8]
mov ecx, [ebp + 12]
.loop2:
mov eax, [esi]
mov ebx, [esi + 4]
cmp eax, ebx
jg .skip
mov [esi], ebx
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] ; save result in eax
mov esp,ebp
pop ebp
ret
; ****************************************************
; function adding two arrays merging them
; esi = address of first array
; edi = address of second array (destination array)
; ****************************************************
mergearrays:
xor ecx, ecx
.merging:
mov eax, [esi + ecx * 4]
xadd [edi + ecx * 4], eax
inc ecx
cmp ecx, ARRAY_LEN
je .mergedone
jmp .merging
.mergedone:
ret
I have to write a bubblesort in C with assembly implement.
My C code looks like :
#include <stdio.h>
extern int arraysort(int array[],int length);
int main () {
int array[]= {7,4,3,6,2,1};
int length = 6;
printf("Unsorted array: %d,%d,%d,%d,%d,%d\n",array[0],array[1],array[2],array[3],array[4],array[5]);
arraysort(array,length);
printf("Sorted array: %d,%d,%d,%d,%d,%d\n",array[0],array[1],array[2],array[3],array[4],array[5]);
return 0;
}
And my assembly code looks like:
.intel_syntax noprefix
.text
.global arraysort
arraysort: # int sortarray(int array[],int length)
#function prologue
push ebp
mov ebp, esp
# function prologue end
push ebx # save ebx for cdecl convection
# 1.argumentum [ebp + 4*2] this is the array
# 2.argumentum [ebp + 4*3] this is the length
mov ecx, [ebp + 12] #array length (6)
dec ecx #array length (5)
mov edx, 1 #variable j
mov esi, [ebp + 8] #array address
loop1:
cmp ecx, 0 # (int i =length; i> length;i--)
jg end
loop2:
mov eax, [esi + 4*ecx] #array[0]
mov ebx, [esi + 4*edx] #array[1]
cmp eax, ebx #if eax > ebx jump to csere
jg swap
dec ecx #i--
inc edx#j++
jz end
jmp loop2
swap:
mov [esi + 4*edx], eax #change the two elements
mov [esi + 4*ecx], ebx
jmp loop2
end:
pop ebx
mov esp, ebp
pop ebp
ret
I dont know what is the problem and I struggling whit this.
If I change in the first loop jg to jl i get infinity loop :/
Sorry for my english and my assembly coding skill but I'm learning this language still.
Please help me! Thank you
Here's the main problem:
mov ecx, [ebp + 12] #array length (6)
dec ecx #array length (5)
mov edx, 1 #variable j
mov esi, [ebp + 8] #array address
loop1:
cmp ecx, 0 # (int i =length; i> length;i--)
jg end
Focus on ecx there. You're basically saying if(--length > 0) goto end;, so you're skipping the entire meat of your function.
Now once you fix that, you'll start getting a segfault. Here's why:
dec ecx #i--
inc edx#j++
jz end
That's equivalent to --i; if(!++j) goto end;. As a result, your loop is going to run way more iterations than you want (until j overflows, but in practice it will segfault first). I'm guessing you meant to switch dec ecx and inc edx, so that the loop would end when i got to 0.
Anyway, with that fixed too, your code will return an updated array, but it will still be wrong. At this point, it's just because your bubble sort is wrong and not because of any assembly-related errors, so I'll stop here.
I'm working on an assembly project, where I need to convert a 'Date-formatted' array, to a number representative array, then bubble sort the number array, then convert the array back to Date-format.
I'm currently JUST trying to test my bubble sort macro with a test number array, and see if it can sort them from least to greatest. I'm not getting any compile errors, but when I run the generated .exe file, the CMD crashes and I have no clue why..
Any help would be appreciated.
This is the current code I'm compiling:
.486 ; create 32 bit code
.model flat, stdcall
option casemap:none
include \masm32\include\masm32rt.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib
.data
dates BYTE "23-JUL-2010", 0, "23-JAN-2010", 0, "23-JUL-2009", 0, "31-JUL-2012", 0, "05-MAR-2010", 0
testArray DWORD 5 DUP(7, 5, 9, 1, 0)
nDates DWORD 5
.code
; ------------- Macros -------------
; Convert Date formatted string (DD-MMM-YYYY) to Number
;DateToNumber MACRO date, number
; TODO
;ENDM
; Convert Number to Date formatted string
;NumberToDate MACRO number, date
; TODO
;ENDM
; Bubble sort an array of integers
BubbleSort MACRO array, length
LOCAL outer
LOCAL inner
LOCAL compare
LOCAL swap
LOCAL done
mov esi, -1
outer:
inc esi
mov edi, -1
cmp esi, length
je done
inner:
inc edi
cmp edi, length - 1
je outer
compare:
mov eax, [array + edi * 4h]
mov ebx, [array + edi * 4h + 4]
cmp eax, ebx
jle inner
swap:
mov [array + edi * 4h], ebx
mov [array + edi * 4h + 4], eax
jmp inner
done:
ENDM
start:
lea EAX, dates ; create pointer to beginning of dates array
mov ECX, nDates ; set up loop counter
BubbleSort testArray, nDates
sub edi, edi
mov edi, -1
printNum_loop:
inc edi
sub esi, esi
mov esi, [testArray + (4h * edi)]
print str$(esi)
print chr$(" ")
cmp edi, 9
jl printNum_loop
print chr$(13,10)
print chr$(13,10)
loop_top:
push EAX ; save EAX and ECX because print macros change these
push ECX
print EAX ; print date at pointer location
print chr$(13,10)
pop ECX
pop EAX
add EAX, 12 ; increment pointer, note that date has 12
; bytes including null-terminator
loop loop_top ; continue loop
inkey ;Keep the window open
exit
end start
I apologize if it's something extremely obvious.. I'm new to assemble/MASM32..
I'm new to assembly language and I'm having trouble with some basic programming problems and I was wondering if you guys could point me in the right direction.
I'm trying to write a function that traverses through an array and sums up the values of its elements. Given given a pointer int *array and some length x.
What I've been able to do so far is write the initial data and place the initial pointer which isn't much but its a start. How would I use a loop in assembly to traverse through the array?
PUSH EBX
PUSH ECX
PUSH EDX
PUSH ESI
PUSH EDI
MOV EBX, array
MOV ECX, x
mov eax, 2;
mov ebx, array;
lea edx, [ebx+eax*4];
You do not need to save all of those registers. If your function uses esi, edi, ebx, ebp, then you must save them in the prologue and restore them in the epilogue. MASM can do that for you with the keyword uses
SomeProcedure proc uses esi, edi, ebx Val1:DWORD, Val2:DWORD
ret
SomeProcedure endp
Here is one way you can do it:
.686
.model flat, stdcall
option casemap :none
include kernel32.inc
includelib kernel32.lib
.data
Array dd 1, 2, 3, 4, 5, 6, 7, 8, 9
Array_Size equ ($ - Array) / 4
.code
start:
push Array_Size - 1
push offset Array
call SumArray
; eax contains sum of array
; print it out here.
push 0
call ExitProcess
SumArray:
push esi ; need to preserve esi
mov esi, [esp + 8] ; address of array
mov ecx, [esp + 12] ; size of array - 1
xor eax, eax ; holds sum
xor edx, edx ; index
AddIt:
add eax, [esi + edx * 4]
inc edx
dec ecx
jns AddIt ; is ecx ! neg repeat loop
pop esi
ret
end start
So we're currently studying Intel 8086 Insertion Sort Code that our professor showed us. He wanted us to figure out why the code skips the 0th element within the array and the 3rd element in the array from a code that he had taken from the web.
; void isort(int *a, int n)
; sorts the first n elements of a
;
; Parameters
; a - pointer to the array
; n - number of elements to sorts
%define a [ebp + 8]
%define n [ebp + 12]
isort:
enter 0, 0
pusha
mov ecx, 1
for:
mov ebx, ecx
imul ebx, 4
add ebx, a
mov ebx, [ebx]
mov edx, ecx
dec edx
while:
cmp edx, 0
jl while_quit
mov eax, edx
imul eax, 4
add eax, a
cmp ebx, [eax]
jge while_quit
mov esi, [eax]
mov dword [eax + 4], esi
dec edx
jmp while
while_quit:
mov [eax], ebx
inc ecx
cmp ecx, n
jl for
popa
leave
ret
And the sample array was {5, 8, 12, 2, 1, 7}. This is more for understanding the 8086 language since we just started a couple days ago, and I was wondering if anyone could explain how and what might be going wrong.
Consider what the code will do when ECX is 1:
The while loop will be entered with EBX=8 and EDX=0.
The jl while_quit will not be taken, since EDX is 0.
EBX is compared to [EAX]. That is; 8 is compared to a[0], which is 5, so the jge while_quit is taken.
mov [eax], ebx stores 8 at a[0], so your array now contains {8,8,12,2,1,7}. Clearly not what you want, since you've lost one of the original elements.
Apart from the code's logical flaw, those imul instructions are completely unnecessary since you can use scaled indices on the x86. So the sorting code can be simplified to this (I've verified that it sorts the array correctly):
mov ecx, 1
for_:
; esi = &a[holePos]
lea esi,[a + ecx*4]
; valueToInsert = a[holePos]
mov ebx, [esi]
while_:
; Did we reach the beginning of the array?
cmp esi, OFFSET a
jle while_quit
; valueToInsert < a[holePos-1] ?
cmp ebx, [esi-4]
jge while_quit
; a[holePos] = a[holePos-1]
mov eax, [esi-4]
mov [esi], eax
; esi = &a[holePos-1]
sub esi,4
jmp while_
while_quit:
; a[holePos] = valueToInsert
mov [esi], ebx
inc ecx
cmp ecx, 6
jl for_
I'm using MASM syntax, but you get the idea.