Reputation: 3684
I have to find min max values in array using only one conditional jump directive.
After compiling and linking the two files below I get a Segmentation Fault (core dumped)
, but I don't understand why that is.
Question: What is causing the segmentation fault?
main.cpp
#include <cstdio>
#include <time.h>
using namespace std;
extern "C" void minmax(int n, int * tab, int * max, int * min);
int main(){
const int rozmiar = 100000;
const int liczba_powtorzen = 10000;
int tab[rozmiar] = {1, 3, 3, -65, 3, 123, 4, 32, 342, 22, 11, 32, 44, 12, 324, 43};
tab[rozmiar-1] = -1000;
int min, max;
min = 99999;
max = -99999;
clock_t start, stop;
start = clock();
for(int i=0; i<liczba_powtorzen; i++){
minmax(rozmiar, tab, &max, &min);
}
printf("min = %d max = %d\n", min, max);
stop = clock();
printf("\n time = %f ( %d cykli)", (stop - start)*1.0/CLOCKS_PER_SEC, (stop - start));
return 0;
}
minmax.asm
global minmax ; required for linker and NASM
section .text ; start of the "CODE segment"
minmax:
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi
mov ecx, [ebp+8] ; array length n
mov esi, [ebp+12] ; array address
mov eax, [ebp+16] ;max
mov edi, [ebp+20] ; min
lp: add eax, [esi] ; fetch an array element
cmp eax, [esi]
jl max ; max<[esi] ->update max
cmp edi, [esi]
jg min ; min>[esi] ->update min
add esi, 4 ; move to another element
loop lp ; loop over all elements
max:
mov eax, esi
ret
min:
mov edi, esi
ret
pop esi ; restore used registers
pop ecx
pop ebp
ret ; return to caller
Upvotes: 0
Views: 148
Reputation: 63797
Long story, short:
You need to restore the stack before using ret
.
Your asm implementation is faulty on many levels, but the reason for your segmentation fault is poor understanding of how ret
works.
Invalid use of ret
ret
does not bring you back to the last jump, it reads the value that is at the top of the stack, and returns to that address.
After you jump to either min:
or max:
, you call ret
, where you should be jumping back to your loop.
This means that it will try to return back to the address at the top of the stack, which certainly isn't a valid address; you modified it upon entering the function.
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi ; note, this is where `ret` will try to go
Upvotes: 3
Reputation: 66
I do not know what you're exactly trying to do, but the assembler function is written poor.
Try this:
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi
mov ecx, [ebp+8] ; array length n
mov esi, [ebp+12] ; array address
mov eax, 0x80000000
mov edi,[ebp+16]
mov [edi], eax
mov eax, 0x7fffffff
mov edi,[ebp+20]
mov [edi], eax
lp:
mov edi,[ebp+16]
lodsd
cmp [edi], eax
jg short _min_test
mov [edi], eax
_min_test:
mov edi,[ebp+20]
cmp [edi], eax
jl short _loop
mov [edi], eax
_loop:
loop lp
pop esi ; restore used registers
pop ecx
pop ebp
ret ; return to caller
Upvotes: 0