The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: magus841 on May 10, 2010, 04:12:49 AM

Title: having a crash issue
Post by: magus841 on May 10, 2010, 04:12:49 AM
Hello yet again! I'm having a bit of trouble and I'm not sure what's going on. I wrote my program in C++ to call an assembler routine to calculate and output all the prime numbers between two input values. But my problem occurs when I try to return to the main program in C++. The program just crashes. I think the problem is that I'm not preserving my registers but I'm unsure how to do that without breaking my program entirely. It finds all the prime numbers. It just crashes at ret. Here's the C++ code:


#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;

extern "C"{
    void IsPrime(long int begvalue, long int endvalue);
}

int main(void) {
    long int start, end;
    float dif;
    long int begvalue = 3, endvalue = 10000;

    start = clock();                         //begin the clock
    IsPrime(begvalue, endvalue);             //reduce the time this call consumes
    end = clock();                           //end the clock

    dif = (end - start)/(float) CLOCKS_PER_SEC;
    cout << "Amount of time to evaluate the potential prime was = " << dif  << "  seconds" << endl;
}



And now here's the assembler code:


TITLE Prime Numbers (main.asm)

;finds prime numbers between two numbers
;outputs those primes

INCLUDE Irvine32.inc

IsPrime PROTO C

.data
end_Val DWORD ?
beg_Val DWORD ?
div_Val DWORD ?

.code
IsPrime PROC C

    push ebp
    mov ebp, esp
   
    mov eax, [ebp + 12]
    mov end_Val, eax

    mov eax, [ebp + 8]
    mov beg_Val, eax

A1:
    ;putting the next value in eax
    mov eax, beg_Val
    cmp eax, end_Val
    je done

    ;starting counter and subtracting 2 from it.
    mov ecx, eax
    sub ecx, 2

    ;set up ebx to use div with
    mov div_Val, 2

Calculate:

    ;Zero out the edx, remainder register
    mov edx, 0;

    ;preserve my testing value
    push eax

    div div_Val
    pop eax
    inc div_Val

    ;Comparing the remainder to zero. number is prime
    ;if the remainder is zero. otherwise continue onto
    ;the next number.
    cmp edx, 0
    je non_prime
    loop Calculate

    call WriteDec
    call Crlf
non_prime:
    inc beg_Val
    jmp A1

done:
    ret
IsPrime ENDP

END


WriteDec just outputs to the console window whatever integer is in the eax register and Crlf just jumps to a new line. And I'm sure there's better ways to calculate prime numbers, but for the purposes of my class, this is fine.

Apologies if this is obvious :( I'm still new to this.
Title: Re: having a crash issue
Post by: jj2007 on May 10, 2010, 06:36:35 AM
try
pushad
    call WriteDec
    call Crlf
popad

EDIT: Sorry, I had not read your code thoroughly. Michael's version will work.
Title: Re: having a crash issue
Post by: MichaelW on May 10, 2010, 07:08:11 AM
Here is your asm source with minimal corrections:

TITLE Prime Numbers (main.asm)

;finds prime numbers between two numbers
;outputs those primes

INCLUDE Irvine32.inc

;--------------------------------------------------------------------
; No need for a PROTO here because the procedure is not invoked from
; this module. And if there were a need, the PROTO should match the
; procedure definition.
;--------------------------------------------------------------------

; IsPrime PROTO C

.data

;------------------------------------------------------------
; Instead of these we can just use the procedure parameters.
;------------------------------------------------------------

;end_Val DWORD ?
;beg_Val DWORD ?

div_Val DWORD ?

.code

;----------------------------------------------------------
; The procedure definition should match the cpp prototype.
;----------------------------------------------------------

IsPrime PROC C beg_Val:DWORD, end_Val:DWORD

;---------------------------------------------------------
; MASM provides the necessary prologue and epilogue code.
;---------------------------------------------------------

;    push ebp
;    mov ebp, esp
;    mov eax, [ebp + 12]
;    mov end_Val, eax
;    mov eax, [ebp + 8]
;    mov beg_Val, eax

A1:
    ;putting the next value in eax
    mov eax, beg_Val
    cmp eax, end_Val
    je done

    ;starting counter and subtracting 2 from it.
    mov ecx, eax
    sub ecx, 2

    ;set up ebx to use div with
    mov div_Val, 2

Calculate:

    ;Zero out the edx, remainder register
    mov edx, 0;

    ;preserve my testing value
    push eax

    div div_Val
    pop eax
    inc div_Val

    ;Comparing the remainder to zero. number is prime
    ;if the remainder is zero. otherwise continue onto
    ;the next number.
    cmp edx, 0
    je non_prime
    loop Calculate

    call WriteDec
    call Crlf
non_prime:
    inc beg_Val
    jmp A1

done:
    ret
IsPrime ENDP

END
Title: Re: having a crash issue
Post by: Tedd on May 10, 2010, 10:12:00 AM
If you must do it this way, a small improvement (but a big time difference):

You only need to check for division against 2, and then all odd numbers up to the square-root of the number to be checked, i.e. you can add 2 each time, since all primes (except 2) are odd.

Advanced: you only need to check division against each prime up to the square-root.
Title: Re: having a crash issue
Post by: dedndave on May 10, 2010, 02:17:55 PM
probably the reason it is crashing is:

the EBX, ESI, EDI, and EBP registers should be preserved
he is only preserving EBP

i am not sure about the C-compiler, but it may also require ECX and/or EDX be preserved
Title: Re: having a crash issue
Post by: clive on May 10, 2010, 03:05:14 PM
You only need to preserve EBX, ESI, EDI (EBP, ESP) across the call, if you don't use them they are implicitly preserved. There are early versions of Watcom C that did not preserve EBX (which is more of a Microsoft rule), Watcom also had register and stack parameter passing modes.

EAX, ECX, and EDX have no preservation requirements.

The subroutine fails to identify loop conditions where the value prior to "sub ecx,2" is ONE or TWO.
Title: Re: having a crash issue
Post by: magus841 on May 10, 2010, 03:22:42 PM
MichaelW's changes actually work perfectly. And I cut a second off the original C++ function. Thank you for the replies. I am very happy now :)
Title: Re: having a crash issue
Post by: dedndave on May 10, 2010, 03:29:25 PM
yes - notice how he was careful not to use EBX, ESI, or EDI
by not using them, you don't have to preserve them   :bg
sometimes, you can write faster code by using one or more of these registers, though