From: kuroikaze on
So yeah I've written this program and I haven't been able to figure
out what I did wrong (aside from the completely insane code written by
a total amateur). I really wish this was Java, as I would have been
done in 10 minutes.

Anyway so the assignment is to enter a 4-digit integer and determine
whether or not it is prime. Then I am to find the prime numbers on
either side of it. So if one put in 23 I should be able to find 19
and 29 (I think those are the closest primes).

I keep getting "integer overflows" according to windbg even when I
tried converting everything to EAX and DWORDS.

This is due Tuesday afternoon (it's Monday night of course!) so
hopefully someone has an idea what I did wrong. Thanks!


..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

From: Frank Kotler on
kuroikaze(a)gmail.com wrote:

....
> Anyway so the assignment is to enter a 4-digit integer

.... which would eliminate certain overflows. But in your code, you seem
to allow six...

> I keep getting "integer overflows" according to windbg even when I
> tried converting everything to EAX and DWORDS.

Probably a "divide overflow" - quotient won't fit in ax. I reacll some
machine I had which reported this error as "divide by zero" (no I
didn't!). Linux (my current version) calls it a "floating point error"
(what floating point???). Converting to 32-bit registers and "dd"
probably won't help. (I'd do it anyway - doing 16-bit ops in 32-bit code
bloats your code with 66h "operation size override prefixes")

> This is due Tuesday afternoon (it's Monday night of course!) so
> hopefully someone has an idea what I did wrong.

Didn't start sooner? :)

> Thanks!
>
>
> .386
> .MODEL FLAT
>
> ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
> INCLUDE io.h ;header file for input/output

Without this, we can't try your code. Since you're in a hurry, I'll take
a wild guess or two anyway...

> 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

What's this return in case of error? -1? (hope not!)

> mov orig, ax ; copy ax to orig
>
> origtest:

Since ax gets altered by the "div" in this loop, you probably want to
reload it each time through.

mov ax, orig

> 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

The "cwd" will zero dx... *provided* ax is non-negative. Four digits
would eliminate this possibility, but with six... ax could get "so big
it's negative". If you intend to handle negative inputs, use "idiv",
else use "xor dx, dx" instead. (the CPU doesn't know if an integer is
"signed" or "unsigned" - depends on what instructions you use - and
"cwd" works on signed values)

> 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

ax is no longer "orig"!

> jmp lowerprimetest
>
> lowerprimetest:
>
> cmp bx, ax

What's in bx at this point? I assume you intend to restart with 2.

> je lowerprime
> cwd
> div bx

Again, the "cwd" is "risky", and ax is altered. In this case, we don't
want to reload ax from "orig" - push/pop ax around the "div"?

> cmp dx, 0
> je lowerloop
> inc bx
> jmp lowerprimetest
>
> lowerprime:
>
> mov lower, ax
> jmp highestloop
>
> highestloop:
>
> add ax, 1

What's ax now? Still "lower"?

> jmp higherprimetest
>
> higherprimetest:
>
> cmp bx, ax
> je higherprime
> cwd
> div bx

Again...

> 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

Run it again in windbg, paying attention to *where* the "divide
overflow" occurs, and watch (e)dx. If it's => (e)bx, there's the problem
(result won't fit in (e)ax).

On thinking about it, my "push ax/pop ax around the div" isn't going to
work well. You've got three nearly identical "isprime" routines. You
know how to do a subroutine? You'll never learn any younger, and it may
simplify this problem.

Lemme play with this and get back to you...

Best,
Frank
From: kuroikaze on

> ... which would eliminate certain overflows. But in your code, you seem
> to allow six...

Suggestions to correct?

> Didn't start sooner? :)
I was out of town and worked on this all night Sunday and afterwork
Monday. I'm trying!


>
> What's this return in case of error? -1? (hope not!)
>
> > mov orig, ax ; copy ax to orig
>
> > origtest:
>
> Since ax gets altered by the "div" in this loop, you probably want to
> reload it each time through.

....doh! I forgot EAX gets changed by the div command.
I would need to reload from orig before incrementing it!
It's possible my overflow errors stem from here.

> mov ax, orig
>
> > 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
>
> The "cwd" will zero dx... *provided* ax is non-negative. Four digits
> would eliminate this possibility, but with six... ax could get "so big
> it's negative". If you intend to handle negative inputs, use "idiv",
> else use "xor dx, dx" instead. (the CPU doesn't know if an integer is
> "signed" or "unsigned" - depends on what instructions you use - and
> "cwd" works on signed values)

Basically I did a find/replace converting everything to eax/ebx/edx.
Words became DWords etc.

Also I put a xor dx,dx before my cwd's cause I didn't know what xor
did,
but I'll got in there and delete all the cwd's.

> What's in bx at this point? I assume you intend to restart with 2.

Yeah..actually I should make sure to include that.


> Lemme play with this and get back to you...
>
> Best,
> Frank

i don't know what push/pop means and since this is assignment 3 in
Assembly 1 I basically know nothing of subroutines or anything else.

i feel this assignment is much too hard compared to the first two and
everyone is struggling with it.

anyway i completely forgot about the io include but all that does is
convert things to ascii with the Ascii to Double (atod) Double to
Ascii (dtoa) kinda stuff. it's provided by my textbook so there's no
problem inside of it.

just in case i'll open it in notepad and post it below:

; IO.H -- header file for I/O macros
; 32-bit version for flat memory model
; R. Detmer last revised 8/2000
..NOLIST ; turn off listing
..386

EXTRN itoaproc:near32, atoiproc:near32
EXTRN dtoaproc:near32, atodproc:near32
EXTRN inproc:near32, outproc:near32

itoa MACRO dest,source,xtra ;; convert integer to ASCII
string

IFB <source>
.ERR <missing operand(s) in ITOA>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in ITOA>
EXITM
ENDIF

push ebx ;; save EBX
mov bx, source
push bx ;; source parameter
lea ebx,dest ;; destination address
push ebx ;; destination parameter
call itoaproc ;; call itoaproc(source,dest)
pop ebx ;; restore EBX
ENDM

atoi MACRO source,xtra ;; convert ASCII string to
integer in AX
;; offset of terminating
character in ESI

IFB <source>
.ERR <missing operand in ATOI>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in ATOI>
EXITM
ENDIF

push ebx ;; save EBX
lea ebx,source ;; source address to EBX
push ebx ;; source parameter on stack
call atoiproc ;; call atoiproc(source)
pop ebx ;; parameter removed by ret
ENDM

dtoa MACRO dest,source,xtra ;; convert double to ASCII
string

IFB <source>
.ERR <missing operand(s) in DTOA>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in DTOA>
EXITM
ENDIF

push ebx ;; save EBX
mov ebx, source
push ebx ;; source parameter
lea ebx,dest ;; destination address
push ebx ;; destination parameter
call dtoaproc ;; call dtoaproc(source,dest)
pop ebx ;; restore EBX
ENDM

atod MACRO source,xtra ;; convert ASCII string to
integer in EAX
;; offset of terminating
character in ESI

IFB <source>
.ERR <missing operand in ATOD>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in ATOD>
EXITM
ENDIF

lea eax,source ;; source address to EAX
push eax ;; source parameter on stack
call atodproc ;; call atodproc(source)
;; parameter removed by ret
ENDM

output MACRO string,xtra ;; display string

IFB <string>
.ERR <missing operand in OUTPUT>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in OUTPUT>
EXITM
ENDIF

push eax ;; save EAX
lea eax,string ;; string address
push eax ;; string parameter on stack
call outproc ;; call outproc(string)
pop eax ;; restore EAX
ENDM

input MACRO dest,length,xtra ;; read string from keyboard

IFB <length>
.ERR <missing operand(s) in INPUT>
EXITM
ENDIF

IFNB <xtra>
.ERR <extra operand(s) in INPUT>
EXITM
ENDIF

push ebx ;; save EBX
lea ebx,dest ;; destination address
push ebx ;; dest parameter on stack
mov ebx,length ;; length of buffer
push ebx ;; length parameter on stack
call inproc ;; call inproc(dest,length)
pop ebx ;; restore EBX
ENDM


..NOLISTMACRO ; suppress macro expansion listings
..LIST ; begin listing

From: Frank Kotler on
kuroikaze(a)gmail.com wrote:

[snip]
> Wow that's a lot to digest. I'll be looking it over and working on
> the assignment all day.

Here's a second shot at it - completely untested, I've probably missed a
few (?) things. I've tried to use instructions you already know (?). You
might want to leave my "first shot" for later.

> I appreciate your help and will probably turn here in the future
> should I get another tough assignment.

Okay... keep in touch and let us know how it's going. We never hear back
about what kind of grade we got, and what (if any) comments were made
about the assignment... what the expected "right answer" was...

> The first two I completed in about 3-4 hours each.

If you wanna get into an extensive discussion... what were they? What
help *is* your course giving you, and what are they leaving out? Get the
damn assignment assembling and running without crashing first - correct
results would be nice. Plenty of time to discuss and improve it - and
plenty of room for improvement!

Best,
Frank


..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

I don't think you need/want this for a PE file...

..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 ?
save_eax DWORD ?


..CODE
_start:

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

origtest:

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


lowerloopinit:
mov ebx, 2

lowerloop:

sub eax, 1
; jmp lowerprimetest

lowerprimetest:

cmp ebx, eax
je lowerprime
;cwd
mov edx, 0
mov save_eax, eax
div ebx
mov eax, save_eax
cmp edx, 0
je lowerloop
inc ebx
jmp lowerprimetest

lowerprime:

mov lower, eax
; jmp highestloop

mov eax, orig
mov ebx, 2

highestloop:

add eax, 1
; jmp higherprimetest

higherprimetest:

cmp ebx, eax
je higherprime
; cwd
mov edx, 0
mov save_eax, eax
div ebx
mov eax, save_eax
cmp edx, 0
je highestloop
inc ebx
jmp higherprimetest

higherprime:

mov higher, eax
jmp finalout

origprime:

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

orignotprime:

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

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

From: kuroikaze on
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?!?

; JJ Sauram - Assignment 3
; Date: 10/18/2007
; Find Prime Numbers


..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





 |  Next  |  Last
Pages: 1 2 3
Prev: DynatOS 64-bit is here!!!
Next: Slow nasm