News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Super Basic 80x86 Assembly Homework Help

Started by Kuroi Kaze, October 23, 2007, 01:33:39 AM

Previous topic - Next topic

Kuroi Kaze

So I'm supposed to do this homework assignment where I take a 4 digit number from the user and determine whether or not it is prime.
Secondly, I need to find the prime numbers on either side of the prime number.

I've written this code and since I'm not really sure how to use WinDbg to figure out what line is causing the trouble, I figured I'd ask here.
Apparently I've written an "Integer Overflow Error" somewhere in here.
Anyway I'm aware this is basically the equivalent of assembly garbage code, but I'm just trying to get through this assignment.

Thanks for your help, as it's due Tuesday afternoon (short time schedule I know but I've been beating my head in on this one).


.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h               ;header file for input/output

cr    EQU   0dh                  ;carriage return character
Lf   EQU   0ah                  ;line feed

.STACK 4096                  ;reserve 4096-byte stack

.DATA                     ;reserve storage for data

prompt1   BYTE   "Please enter a four digit integer:  ", 0
prompt2   BYTE   cr, Lf, " is not a prime number.", 0
prompt3 BYTE   cr, Lf, " is a prime number.", 0
prompt4 BYTE   cr, Lf, "Largest prime number smaller than ", 0
prompt5 BYTE   cr, Lf, "Smallest prime number larger than ", 0
string   BYTE   11 DUP (?)
orig   WORD   ?
lower   WORD   ?
higher  WORD   ?


.CODE
_start:

mov bx, 2
output prompt1
input string, 6
atoi string      ; put input in ax
mov orig, ax   ; copy ax to orig

origtest:

cmp bx, ax      ; subtract input from bx
je origprime   ; if input and bx are = then jump
cwd            ; convert to word
div bx         ; divide ax by bx
cmp dx, 0      ; sub ax minus 0
je orignotprime   ; if 0 and dx are = then jump
inc bx         ; increment bx register
jmp origtest   ; restart loop

lowerloop:

sub ax, 1
jmp lowerprimetest

lowerprimetest:

cmp bx, ax
je lowerprime
cwd
div bx
cmp dx, 0
je lowerloop
inc bx
jmp lowerprimetest

lowerprime:

mov lower, ax
jmp highestloop

highestloop:

add ax, 1
jmp higherprimetest

higherprimetest:

cmp bx, ax
je higherprime
cwd
div bx
cmp dx, 0
je highestloop
inc bx
jmp higherprimetest

higherprime:

mov higher, ax
jmp finalout

origprime:

mov bx, 2
mov ax, orig
itoa string, ax ; Convert ax to Ascii
output string   ; Output: ax
output prompt2   ; is a prime number
jmp lowerloop

orignotprime:

mov bx, 2
mov ax, orig
itoa string, ax
output string
output prompt3   ; is not a prime number
jmp lowerloop

finalout:

output prompt4   ; Largest number smaller than
mov ax, lower
itoa string, ax
output string
output prompt5   ; Smallest number greather than
mov ax, higher
itoa string, ax
output string


INVOKE ExitProcess, 0

PUBLIC _start

END

Kuroi Kaze

Hmm using OllyDBG it looks like one of the div statements might be the problem?

Any help?

Jackal

poissibly need to xor dx,dx in front of the DIV's.. I know when i started to use DIV i had to clear edx before i devided or i would get overfllow.

Mark Jones

Hello. Do you have the MASM32 package? If so, look in \masm32\help\opcodes.hlp and find DIV. This gives the various ways it can be used and the requirements. Look through your code -- is it a course requirement to use word-sized registers? If not, use 32-bit registers, such as
XOR edx,edx
MOV EAX,Numerator
MOV ECX,Divisor
DIV ECX
; Whole number in EAX
; Remainder in EDX


"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Kuroi Kaze

We haven't covered the XOR command yet.  : )

I'll try clearing EDX and see if that works! 
I'll reply back if that fixed things.

Thanks.

Kuroi Kaze

Okay...that did...something?  It runs but seems to hang infinitely and needs CTRL-C'd for some reason.
Plus what it outputs doesn't look right either.

I've revised the code as mentioned and here it is now:




.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ;header file for input/output

cr EQU 0dh ;carriage return character
Lf EQU 0ah ;line feed

.STACK 4096 ;reserve 4096-byte stack

.DATA ;reserve storage for data

prompt1 BYTE "Please enter a four digit integer:  ", 0
prompt2 BYTE cr, Lf, " is not a prime number.", 0
prompt3 BYTE cr, Lf, " is a prime number.", 0
prompt4 BYTE cr, Lf, "Largest prime number smaller than ", 0
prompt5 BYTE cr, Lf, "Smallest prime number larger than ", 0
string BYTE 11 DUP (?)
orig DWORD ?
lower   DWORD ?
higher  DWORD ?


.CODE
_start:

mov ebx, 2
output prompt1
input string, 11
atod string ; put input in eax
mov orig, eax ; copy eax to orig

origtest:

cmp ebx, eax ; subtract input from ebx
je origprime ; if input and ebx are = then jump
cwd ; convert to word
XOR edx,edx
div ebx ; divide eax by ebx
cmp edx, 0 ; sub eax minus 0
je orignotprime ; if 0 and edx are = then jump
inc ebx ; increment ebx register
jmp origtest ; restart loop

lowerloop:

sub eax, 1
jmp lowerprimetest

lowerprimetest:

cmp ebx, eax
je lowerprime
cwd
XOR edx,edx
div ebx
cmp edx, 0
je lowerloop
inc ebx
jmp lowerprimetest

lowerprime:

mov lower, eax
jmp highestloop

highestloop:

add eax, 1
jmp higherprimetest

higherprimetest:

cmp ebx, eax
je higherprime
cwd
XOR edx,edx
div ebx
cmp edx, 0
je highestloop
inc ebx
jmp higherprimetest

higherprime:

mov higher, eax
jmp finalout

origprime:

mov ebx, 2
mov eax, orig
dtoa string, eax ; Convert eax to Ascii
output string ; Output: eax
output prompt2 ; is a prime number
jmp lowerloop

orignotprime:

mov ebx, 2
mov eax, orig
dtoa string, eax
output string
output prompt3 ; is not a prime number
jmp lowerloop

finalout:

output prompt4 ; Largest number smaller than
mov eax, lower
dtoa string, eax
output string
output prompt5 ; Smallest number greather than
mov eax, higher
dtoa string, eax
output string


INVOKE ExitProcess, 0

PUBLIC _start

END



MichaelW

For the first version of your code, in addition to an overflow caused by not zeroing DX (or EDX) before the divide operations, the code returned "is prime" for all inputs that I tested, and then crashed from a divide by zero in the higherprimetest loop.
eschew obfuscation

Kuroi Kaze

Yeah I realized that div changes EAX but I wasn't accounting for it in my code.

Most of the places I'm working with EAX need to be ECX so they don't get fubar'd by the divs.

There's still a lot more to work on, but you expertise with the debugger will give me some places to check out.

Thanks a million!

Kuroi Kaze

Okay here's the re-written overflow-free error code.

Unfortunately it doesn't work right.

1059 is my "control" test and the answers that should come out are not what come out of my program.

When I put in 1059 I should get 1051 and 1061 are the two primes.
Instead I get 1053 and 1060?!? 



.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ;header file for input/output

cr EQU 0dh ;carriage return character
Lf EQU 0ah ;line feed

.STACK 4096 ;reserve 4096-byte stack

.DATA ;reserve storage for data

prompt1 BYTE "Please enter a four digit integer:  ", 0
prompt2 BYTE cr, Lf, " is not a prime number.", 0
prompt3 BYTE cr, Lf, " is a prime number.", 0
prompt4 BYTE cr, Lf, "Largest prime number smaller than ", 0
prompt5 BYTE cr, Lf, "Smallest prime number larger than ", 0
string BYTE 11 DUP (?)
orig DWORD ?
lower   DWORD ?
higher  DWORD ?


.CODE
_start:

mov ebx, 2
output prompt1
input string, 6
atod string ; put input in eax
mov orig, eax ; copy eax to orig
mov ecx, eax

origtest:

cmp ebx, eax ; subtract input from ebx
je origprime ; if input and ebx are = then jump
XOR edx,edx ; zero out edx
div ebx ; divide eax by ebx
cmp edx, 0 ; sub eax minus 0
je orignotprime ; if 0 and edx are = then jump
inc ebx ; increment ebx register
mov eax, ecx ; put the original test back in eax
jmp origtest ; restart loop

lowerloop:

sub ecx, 1
jmp lowerprimetest

lowerprimetest:

mov eax, ecx
cmp ebx, eax
je lowerprime
XOR edx,edx
div ebx
cmp edx, 0
je lowerloop
inc ebx
jmp lowerprimetest

lowerprime:

mov lower, ecx
mov ecx, orig
jmp highestloop

highestloop:

add ecx, 1
jmp higherprimetest

higherprimetest:

mov eax, ecx
cmp ebx, eax
je higherprime
XOR edx,edx
div ebx
cmp edx, 0
je highestloop
inc ebx
jmp higherprimetest

higherprime:

mov higher, ecx
jmp finalout

origprime:

mov ebx, 2
dtoa string, ecx ; Convert ecx to Ascii
output string ; Output: ecx
output prompt2 ; is a prime number
jmp lowerloop

orignotprime:

mov ebx, 2
dtoa string, ecx
output string
output prompt3 ; is not a prime number
jmp lowerloop

finalout:

output prompt4 ; Largest number smaller than
mov eax, lower
dtoa string, eax
output string
output prompt5 ; Smallest number greather than
mov eax, higher
dtoa string, eax
output string


INVOKE ExitProcess, 0

PUBLIC _start

END


raymond

Although it's not the optimal way to test if a number is prime, you first check if it's even (therefore not prime if it is). You then check if it is divisible by ODD numbers only (no use checking if it is divisible by even numbers). So you set BX (or EBX) =3 as the initial divisor and increment it by 2 for each loop. You break out of the loop when the quotient of the division becomes smaller than the divisor (incrementing the divisor any more will only give you smaller and smaller quotients). At that point, you know you have a prime.

For lower primes, you take your input number and decrement it by 1 if it is even or by 2 if it is odd, to make sure you start with an odd number. You then check that number for prime and decrement it by 2 until you do get a prime. You do the same to find the higher prime by incrementing the target odd number by 2 until you get the required prime.

Let's see you code it now. :clap: :clap:

If you ever have many numbers to check for primality, a more efficient way is to first build a table of primes up to the maximum expected to be needed (usually equal to the square root of the largest number to be checked plus the next one). You then use only those primes as divisors.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com