;=== Subprogram liner_search ===
linear_search:

segment .data

outof db  "Got out of loop", 0
notf db    "Got to not_found", 0

segment .bss

segment .text
push  ebp         ; push all registers onto stack
mov    ebp, esp         ; copy esp into ebp to hold place on stack
push  ebx
push  ecx

mov    ebx, ; copy start address of array into ebx
mov    ecx,         ; copy size of array into ecx
mov    eax,         ; copy dw to be found into eax
sub    ebx, 4 ; setupd array pointer to enter loop

search_loop:
add    ebx, 4 ; increment array pointer to next slot
cmp    eax, ; compare value to be found with value in array
loopne search_loop ; return to beginning of loop if not equal and ecx!=0
cmp    eax, ; compare value to be found with value in array
jne    number_not_found ; jump to number_not_found if eax !=
mov    eax, ; move size of array to eax
sub    eax, ecx         ; compute array index of number
mov    , eax         ; put index in stack for main
jmp    done ; jump to end of subprogram
number_not_found:
mov    eax, 0 ; move 0 into eax to return not found value
mov    , eax         ; move 0 into stack for main
done:
pop    ecx
pop    ebx
pop    ebp
ret
;==== End of subprogram linear_search




This is my subprogram linear_search for a main.
If i include the element to be found in the array, it return the index of the element fine,
However, if the element is not in the array it throws a segmentation fault instead of returning a zero

I've tried adding comments in after program should end loop and then cmp again to see if loop ended because value was found, or because
ecx = 0 and value not found... however, program seems to crash where loopne checks value!=element and ecx=0..

PLEASE HELP
Posted on 2010-04-02 13:18:49 by ZosoLzrd
Don't use so much registers and loopne...
You can try something like this:

SrchDD proto :dword,:dword,:dword
...
How to call:
invoke SrchDD,  addr addr_array, dwsize, dwsrchpathern
jc Not_found
Found:
.....
......
Not_found:
...
...
SrchDD    proc  lpsaddr:dword, lpsize:dword, npathern:dword
 pop ecx ; return address
 pop eax ; eax->start address of array
 pop ecx ; ecx-> size of array into ecx
 pop edx ; edx-> dw to be found into eax
 add ecx, eax ; ecx->last address of array
@@:
 cmp   edx,    ; compare value to be found with value in array
 je @f
 add   eax, 4        ; increment array pointer to next slot
 cmp eax, ecx
 jle @b
 stc                           ; set carry flag=1 ->flag for not_found
 jmp dword ptr     ; return carry flag=1 and jmp to return address
@@:
         sub   eax,           ; eax-> index  
 jmp dword ptr     ; return the index in EAX and jmp to return address
SrchDD    endp
Posted on 2010-04-02 15:59:15 by lingo12
well this is a project for class, and the professor wants us to do it only with what we've learned in class thus far...

I've been messing with my program, and it looks like the problem is that loopne does not exit
when it gets to the last element of the array (the size which is stored in ecx)...
it just keeps looping and then segmentation fault.... any ideas?
Posted on 2010-04-02 16:02:01 by ZosoLzrd
What are the units of "size of array" that you're putting in ecx? If that's in bytes, there's your problem! ecx should be "number of dwords". If that isn't it... keep lookin'...

You shouldn't need to put the index back on the stack, once you've calculated it - just return it in eax... that's the "usual way"... (from the way you're calculating the index, looks as if "size of array" is in dwords... so the question might be "what are you actually passing it?")

Best,
Frank

Posted on 2010-04-02 18:00:42 by fbkotler
i declared the size variables as:
size1 resd 1
so they are double words.

The problem is just when the element to be found isn't in the array... the loop keeps going when ecx is 0
Works fine when the element is in the array
Posted on 2010-04-02 18:03:12 by ZosoLzrd

...
SrchDD    proc  lpsaddr:dword, lpsize:dword, npathern:dword
  pop ecx ; return address
  pop eax ; eax->start address of array
  pop ecx ; ecx-> size of array into ecx
  pop edx ; edx-> dw to be found into eax
  add ecx, eax ; ecx->last address of array
@@:
  cmp  edx,     ; compare value to be found with value in array
  je @f
  add  eax, 4        ; increment array pointer to next slot
  cmp eax, ecx
  jle @b
  xor eax, eax      ; eax=0 ->is a flag for not_found
  jmp dword ptr     ; return zero in EAX and jmp to return address
@@:
          sub  eax, ; eax-> index  
  jmp dword ptr     ; return the index in EAX and jmp to return address
SrchDD    endp



Interesting technique. Did you see that somewhere, or think it up yourself? I don't think it's very "robust", but... interesting...

ZosoLzrd,

Yes, the "size" of "size of array" is dword, but what are the "units"? I'm not making myself clear... what number is going in ecx? Number of bytes in the array? Or number of dwords in the array? You're treating it as if it were the latter. I doubt if "loop" is continuing when ecx is zero. But if ecx were number of bytes in the array, it would continue longer than it should (ebx will be past the end of your array - segfault!) If all else fails, post the calling code.

Best,
Frank

Posted on 2010-04-02 18:30:49 by fbkotler
Oh sorry.
ecx holds the number of dwords in the array.
Posted on 2010-04-02 18:32:41 by ZosoLzrd
i understand what you're saying about it counting the bytes.
But i checked that ecx = the number of integers inputed in the array before entering the loop.
Posted on 2010-04-02 18:38:46 by ZosoLzrd
"Did you see that somewhere, or think it up yourself? "
You can search this and hutch's forums about my "technique"...

"I don't think it's very "robust", but... interesting..."
Don't think, just measure it for speed...  ;)
Posted on 2010-04-02 18:52:12 by lingo12
For what shall I search, "lingo12's technique"?

ZosoLzrd,

Okay, I'm gonna have to test this, wait a second... okay... Works for me. If the "needle" is the first dword in the array, you're returning 1, while I'd call that "index 0" (you're using zero for "not found"), but it works, found or not. What's different? Got me!

A common bug is to put a call to a C function in the middle of a loop - C is allowed to trash ecx - but you haven't done that. I don't see the problem. Just to make sure we're comparing apples with apples, here's what I tested:


;=== Subprogram liner_search ===

global _start
section .text
_start:
    nop
    push 42
    push 5
    push array
    call linear_search
    add esp, 4 * 3
   
    mov ebx, eax ; make index the exitcode - view with "echo $?"
   
    mov eax, 1
    int 80h

;  I'd really like to see this label moved, but it works like this...
linear_search:

segment .data

array dd 0, 1, 2, 3, 2


outof db  "Got out of loop", 0
notf db    "Got to not_found", 0

segment .bss

segment .text

; linear_array:
push  ebp                          ; push all registers onto stack
mov    ebp, esp                      ; copy esp into ebp to hold place on stack
push  ebx
push  ecx

mov    ebx,               ; copy start address of array into ebx
mov    ecx,                     ; copy size of array into ecx
mov    eax,                     ; copy dw to be found into eax
sub    ebx, 4                  ; setupd array pointer to enter loop

search_loop:
  add    ebx, 4              ; increment array pointer to next slot
  cmp    eax,             ; compare value to be found with value in array
  loopne search_loop            ; return to beginning of loop if not equal and ecx!=0
  cmp    eax,             ; compare value to be found with value in array
  jne    number_not_found        ; jump to number_not_found if eax !=
  mov    eax,            ; move size of array to eax
  sub    eax, ecx                    ; compute array index of number
  mov    , eax                ; put index in stack for main
  jmp    done              ; jump to end of subprogram
number_not_found:
  mov    eax, 0              ; move 0 into eax to return not found value
  mov    , eax                ; move 0 into stack for main
done:
  pop    ecx
  pop    ebx
  pop    ebp
  ret
;==== End of subprogram linear_search


What am I missing???

Best,
Frank



Posted on 2010-04-02 19:31:34 by fbkotler
Ok so how my program works is, it ask user to input integers for 2 arrays.
right now im only using the first array to test my linear search subprogram.
I have the program set to look for '5' in the array.
So if i enter 5 into the array, it will return and show the index of '5' in the array...
Really its the index+1 because the first index would return as 1 as opposed to 0.

To test how many times the loop runs i put the following code:
call    print_int
call    print_nl

to print eax '5' everytime it ran through the loop.
It came out to be over 800 times and finally a seg fault...

I dont know why it works for you...


Here is all my code, maybe it'll be some help

%include "asm_io.inc"

segment .data

welcome  db    "Welcome to Assignment 4 by Anthony Gonzalez.", 0

intro    db    "This program will demonstrate the union and intersection of arrays.", 0

first    db    "Please enter double words for first array.", 0

second  db    "Please enter double words for second array.", 0

thisis  db    "This is the location of the found variable: ", 0

afterpush db  "The problem is after push for linear_Search, and before calling it.",0
aftersearch db "The problem is after linear search.", 0

segment .bss

array1 resd 50 ; first array for input
array2 resd 50 ; second array for input
;union resd 100 array used for union of two arrays
;intersection resd 50     array used for intersection of two arrays
size1 resd 1 ; size of first array
size2 resd 1 ; size of second array
;unionsize resd 1 size of union array
;intersectsize resd 1 size of intersection array
location resd 1 ; location holder for linear_search

segment .text
      global  asm_main               
asm_main:                             

enter    0,0                    ; setup routine
pusha ; push all registers on stack

mov    eax, welcome ; move welcome message into eax
call  print_string ; print welcome message
call  print_nl ; print new line

mov    eax, intro ; move intro message into eax
call  print_string ; print intro message
call  print_nl ; print new line

mov    eax, first ; move first prompt into eax for printing
call  print_string ; print prompt to screen
call  print_nl ; print new line

push  array1 ; push array1 onto stack for get_array
push  size1 ; push size1 onto stack to count entries for array1

call  get_array ; call subprogram get_array to fill first array

pop    dword ; pop counter from stack into size2
pop    edx ; pop to discard start of array

mov    eax, 5

push  eax
push  size1
push  array1

call  linear_search

pop    edx
pop    edx
pop    eax

call  print_int
call  print_nl

mov    eax, thisis
call  print_nl
call  print_string



;  --- clean up procedure ---
dump_regs 97
dump_mem  98, array1, 2
mov    ebp, esp
dump_stack 99, 2, 3

popa
mov    eax, 0
leave
ret

;======== End of Main ========



;=== Subprogram get_array===
get_array:

segment .data

moreinputs db    "Are the more inputs to be entered(Y=1 or N=0)? ", 0
enterprompt db    "Enter next number: ", 0

segment .bss

segment .text
pusha
mov    ebp, esp ; copy esp into ebp to hold place on stack

mov    edx, ; move array into edx from stack
mov    ecx, 0 ; move size counter for array into ecx from stack

mov    eax, moreinputs ; move inputs prompt for printing
call  print_string ; print inputs prompt
call  read_int

if:
cmp    eax, 1
jne    endif

beginloop: ; statement to start while loop
mov    eax, enterprompt ; move enterprompt into eax for printing
call  print_string ; print enterprompt
call  read_int ; read integer from keyboard
mov    , eax ; place integer incoming integer into array
add    ecx, 1 ; increment counter for array size
;
mov    eax, moreinputs ; move inputs prompt for printing
call  print_string ; print inputs prompt
call  read_int ;
cmp    eax, 1 ; 8-bit comparison, if equal then zf = 1, otherwise zf =0
je    beginloop ; jump to start of loop if zf = 1
;
endif:

mov    , ecx ; copy counter into stack where size is.

popa
ret
;==== End of Subprogram get_array ====


;=== Subprogram liner_search ===
linear_search:

segment .data

outof db  "Got out of loop", 0
notf db    "Got to not_found", 0

segment .bss

segment .text
push  ebp ; push all registers onto stack
mov    ebp, esp ; copy esp into ebp to hold place on stack
push  ebx
push  ecx

mov    ebx, ; copy start address of array into ebx
mov    ecx, ; copy size of array into ecx
mov    eax, ; copy dw to be found into edx
sub    ebx, 4 ; setupd array pointer to enter loop

search_loop:
  add    ebx, 4              ; increment array pointer to next slot
  cmp    eax,             ; compare value to be found with value in array
  loopne search_loop            ; return to beginning of loop if not equal and ecx!=0
  cmp    eax,             ; compare value to be found with value in array
  jne    number_not_found        ; jump to number_not_found if eax !=
  mov    eax,            ; move size of array to eax
  sub    eax, ecx                    ; compute array index of number
  mov    , eax                ; put index in stack for main
  jmp    done              ; jump to end of subprogram
number_not_found:
  mov    eax, 0              ; move 0 into eax to return not found value
  mov    , eax                ; move 0 into stack for main
done:
  pop    ecx
  pop    ebx
  pop    ebp
  ret
;==== End of subprogram linear_search
Posted on 2010-04-02 19:55:18 by ZosoLzrd
Ah! "push size1" pushes the address of the variable - "push dword Posted on 2010-04-02 20:41:44 by fbkotler
WOW! It works!
I can't believe such a little thing could cause me so much grief!

Thanks so much!
Posted on 2010-04-02 20:49:30 by ZosoLzrd

I can't believe such a little thing could cause me so much grief!


Welcome to assembly programming :)
Posted on 2010-04-03 07:46:22 by Scali