.686 ; create 32 bit code
.Model flat, StdCall ;32 bit memory model
Option CaseMap :none ; case sensitive
Include \masm32\include\windows.inc
Include \masm32\macros\macros.asm ; MASM support macros
; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
Include \masm32\include\masm32rt.inc
; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
IncludeLib \masm32\lib\msvcrt.lib
.Code
start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Call Main
inkey ; pause the screen while waiting for user to press any key
; to continue
exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Main Proc Uses Ecx
Local Number:DWord
Local Remainder:DWord
Local Quotient:DWord
Local Factor:DWord
Local PrimeFactor:DWord
Local WantContinue:DWord
; Number is the integer to be factored out
; PrimeFactor is the string containing the factored primes of the user's integer
; WantContinue is the sentinel value of the first while loop
;-----------------------------------------------------------
Mov WantContinue, 0
Mov PrimeFactor, " "
.While ((WantContinue >= 0) && (WantContinue < -1))
print chr$(13, 10)
Mov Number, sval(input("Enter an integer value for Number : "))
Mov Factor, 2
Mov Ecx, Number
.If (Ecx >= 2)
.While Factor <= Ecx ; Factor <= (Number = Ecx)
Mov Eax, Number
Mov Ebx, Factor
Cdq
IDiv Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
IDiv Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.If (Remainder == 0)
Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor))
Mov Quotient, Ecx ; Quotient = Number = Ecx
Mov Eax, Number
Mov Ebx, Factor
Cdq
IDiv Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
IDiv Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.ElseIf
Inc Factor ; Factor = Factor + 1
.EndIf
.EndW
print str$(Ecx)
print chr$(" = ")
print str$(PrimeFactor) ; output the prime factorization of the number
print chr$(13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.ElseIf (Number == 1)
print str$(Number)
print chr$(" = ")
print str$(Number)
print chr$(13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.ElseIf (Number <= 0)
print chr$(13, 10)
print chr$("Invalid integer entered!")
print chr$(13, 10, 13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.EndIf
.EndW
print chr$(13, 10) ; a return key space will be outputted to the screen
Ret
Main EndP
End start
---------------------------------------------------------------------------------------------------
The above code does not work.
For example,
Here is how the code should work,
If Number = 30, The PrimeFactor will display --> 30 = 2 * 3 * 5 on the screen
If Number = 72, The Prime Factor will display --> 72 = 2 * 2 * 2 * 3 * 3 on the screen
PrimeFactor is a string.
The instruction: Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor)) does not seem to work. Did I write out this instruction wrong?
Please help me.
Thanks
Which error message do you get? It would also help readers if you put the lines that don't work in bold...
.686 ; create 32 bit code
.Model flat, StdCall ;32 bit memory model
Option CaseMap :none ; case sensitive
Include \masm32\include\windows.inc
Include \masm32\macros\macros.asm ; MASM support macros
; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
Include \masm32\include\masm32rt.inc
; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
IncludeLib \masm32\lib\msvcrt.lib
.Code
start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Call Main
inkey ; pause the screen while waiting for user to press any key
; to continue
exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Main Proc Uses Ecx
Local Number:DWord
Local Remainder:DWord
Local Quotient:DWord
Local Factor:DWord
Local PrimeFactor:DWord
Local WantContinue:DWord
; Number is the integer to be factored out
; PrimeFactor is the string containing the factored primes of the user's integer
; WantContinue is the sentinel value of the first while loop
;-----------------------------------------------------------
Mov WantContinue, 0
Mov PrimeFactor, " "
.While ((WantContinue >= 0) && (WantContinue < -1))
print chr$(13, 10)
Mov Number, sval(input("Enter an integer value for Number : "))
Mov Factor, 2
Mov Ecx, Number
.If (Ecx >= 2)
.While Factor <= Ecx ; Factor <= (Number = Ecx)
Mov Eax, Number
Mov Ebx, Factor
Cdq
IDiv Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
IDiv Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.If (Remainder == 0)
Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor)) Mov Quotient, Ecx ; Quotient = Number = Ecx
Mov Eax, Number
Mov Ebx, Factor
Cdq
IDiv Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
IDiv Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.ElseIf
Inc Factor ; Factor = Factor + 1
.EndIf
.EndW
print str$(Ecx)
print chr$(" = ")
print str$(PrimeFactor) ; output the prime factorization of the number print chr$(13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.ElseIf (Number == 1)
print str$(Number)
print chr$(" = ")
print str$(Number)
print chr$(13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.ElseIf (Number <= 0)
print chr$(13, 10)
print chr$("Invalid integer entered!")
print chr$(13, 10, 13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.EndIf
.EndW
print chr$(13, 10) ; a return key space will be outputted to the screen
Ret
Main EndP
End start
---------------------------------------------------------------------------------------------------
The lines in red bold color is the ones I have trouble with.
There are no error messages.
When I enter Number -1 and Numbers less than -1, the program gets stuck in an infinite loop.
Only Numbers 0 and 1 respond to the program.
Numbers 2 and greater gets the program stuck in an infinite loop too.
The high-level constructs (.IF, .WHILE, .REPEAT), PROTO, and INVOKE by default treat initializers as unsigned. To change this behavior, precede the initializer with SBYTE PTR, SWORD PTR, or SDWORD PTR.
mov eax, 1
.IF eax > -1
; This tests for eax > 0FFFFFFFFh
.ENDIF
mov eax, 1
.IF eax > SDWORD PTR -1
; This tests for eax > -1
.ENDIF
Quote from: MichaelW on January 25, 2008, 01:22:58 AM
The high-level constructs (.IF, .WHILE, .REPEAT), PROTO, and INVOKE by default treat initializers as unsigned.
Thanks, Michael. I also stumbled over this counter-intuitive behaviour some time ago, and am still looking for a plausible case where using IF with an unsigned integer (the default) would make any sensible difference to using it with a signed integer...
Main Proc
Local FactorString:Dword
Local Factor:Dword
; FactorString is a string to store the accumulated characters to build up the string
; Factor is a number
Mov FactorString, "1"
Mov Factor, 2
.while (Factor <= 20)
Mov FactorString, cat$(str$(FactorString), chr$(" * "), str$(Factor))
add Factor, 1
.endw
print str$(FactorString) ; print out the accumulated string from the while loop
ret
Main EndP
---------------------------------------------------------------------
For the code above, is this the correct way to accumulate a string by building it up in a while loop and later printing it out? Also, did I declare the variable for a string to accumulate correctly in the above code?
Please help.
Thanks
hi
I have the updated code below
The code below is giving me an infinite loop
-------------------------------------------------------------------------------------------------------
.686 ; create 32 bit code
.Model flat, StdCall ;32 bit memory model
Option CaseMap :none ; case sensitive
Include \masm32\include\windows.inc
Include \masm32\macros\macros.asm ; MASM support macros
; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
Include \masm32\include\masm32rt.inc
; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
IncludeLib \masm32\lib\msvcrt.lib
.Code
start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Call Main
inkey ; pause the screen while waiting for user to press any key
; to continue
exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Main Proc Uses Esi
Local Number:DWord
Local Remainder:DWord
Local Quotient:DWord
Local PrimeFactor:DWord
Local Factor:DWord
Local PrimeFactorBuffer[1024]:Byte
Local primeCounter:DWord
Local WantContinue:DWord
; Number is the integer to be factored
; PrimeFactor is the string containing the factored primes of the user's integer
; WantContinue is the sentinel value of the first while loop
;-----------------------------------------------------------
Lea Eax, PrimeFactorBuffer
Mov PrimeFactor, Eax
Mov PrimeFactor, " "
Mov WantContinue, 0
.While ((WantContinue >= 0) && (WantContinue < -1))
print chr$(13, 10)
Mov Number, sval(input("Enter an integer value for Number : "))
Mov Factor, 2
Mov Esi, Number
.If (Esi <= SDWord Ptr 1) ; if (Esi <= 1)
print chr$(13, 10)
print chr$("Invalid integer entered!", 13, 10)
print chr$("An integer must be greater than 1!", 13, 10)
print chr$(13, 10, 13, 10)
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.ElseIf (Esi > 1)
print str$(Esi)
print chr$(" = ")
Mov primeCounter, 1
.While Factor <= Esi ; Factor <= (Number = Esi)
Mov Eax, Number
Mov Ebx, Factor
Cdq
Div Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
Div Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.If (Remainder == 0)
.If (primeCounter > 1)
print cat$(str$(PrimeFactor), chr$(" * "), str$(Factor))
.ElseIf (primeCounter == 1)
Mov Eax, Factor
Mov PrimeFactor, Eax
print str$(PrimeFactor)
.EndIf
Mov Quotient, Esi ; Quotient = Number = Esi
Mov Eax, Number
Mov Ebx, Factor
Cdq
Div Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Cdq
Mov Ebx, Factor
Div Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
.ElseIf (Remainder != 0)
Inc Factor ; Factor = Factor + 1
Inc primeCounter
.EndIf
print chr$(13, 10)
.EndW
Mov WantContinue, sval(input("Enter -1 to quit program : "))
print chr$(13, 10)
.EndIf
.EndW
print chr$(13, 10) ; a return key space will be outputted to the screen
Ret
Main EndP
End start
--------------------------------------------------------------------------------------------
The code in red above I believe in giving me an infinite loop problem
I get an infinite display loop above
The following are examples of my input.
If I enter 2 for Number I get the following:
2
2
2
2
2
2
2
2
2
.
.
.
.
more 2's displayed to infinity
if I enter 3 for Number I get the following
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
.
.
.
.
.
.
more "32 * 3" 's displayed to infinity
if I enter 23 for Number
I get empty space displayed to infinity
<blank space>
.
.
.
.
.
.
.
.
<blank space>
This applies to your Reply #6 post:
Your code is not allocating a buffer to hold the string. To create a local string, 100 bytes in length, you can use something like this:
Local FactorString[100]:BYTE
The cat$ macro requires that the buffer contain a null-terminated string, or that the first byte be set to zero to indicate that the string is empty. To set the first byte to zero you can use an instruction like this:
mov FactorString, 0
Then you can use the cat$ macro to set the first factor in the string. Note that there are other, more efficient ways of doing this, but they are harder to understand. Note also that there is no need here for a separate variable to hold the address of the string buffer, because in the code you can just use "ADDR FactorString" to pass the address. Note also that cat$ can accept quoted strings, and that there is no need here for the returned address, so this instruction just copies the returned address to a scratch register, effectively discarding it.
mov eax, cat$(ADDR FactorString, "1")
And in the loop, you could use something like this to add the factor to the string:
mov eax, cat$(ADDR FactorString, "*", str$(Factor))
And to print the string and move the text cursor to the next line, something like this:
print ADDR FactorString,13,10
Edit:
I think you need to avoid writing some large chunk of sloppy code, that repeats many of the same errors in your previous posts, and then dumping it on the forum expecting us to debug it for you. I think you don't understand how difficult it is to look at your code and understand what you are trying to do, and without understanding what you are trying to do, it's hard to know what is an error, and what is a side effect of some error. Before you went on to each succeeding post, you should have made sure that you understood the errors in your previous posts. The logic in your Reply #7 post is complex and hard to follow, and that means that it's likely to contain errors, and that the errors will be hard to find. There is a reason why experienced programmers generally don't write code like this.
Also, you should avoid posting the same question in more than one thread.
etow,
1. I think the problem is in the *** .While Factor <= Esi *** loop.
It never change. And Number never change. I think you dont want it.
2. Why do you need to divide the Number again inside *** .If (Remainder == 0) ***
3. Suppose Number=6. With Factor=2, the first division gives: Quotient=3 and
Remainder=0.
To the Next division, the Number should be Number=3=Quotient. NOT the same 6.
Isnt it ? So ...
4. To simplify your code
;change this
Mov Eax, Number
Mov Ebx, Factor
Cdq
Div Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Eax, Number
Mov Ebx, Factor
Cdq
Div Ebx
Mov Remainder, Edx ; Remainder = Number mod Factor
; by this
Mov Eax, Number
Mov Ebx, Factor
Cdq
Div Ebx
Mov Quotient, Eax ; Quotient = Number / Factor
Mov Remainder, Edx ; Remainder = Number mod Factor
EDIT: read what MichaelW said
RuiLoureiro
Quote from: MichaelW on January 25, 2008, 04:20:51 PM
Local FactorString[100]:BYTE
.. To set the first byte to zero you can use an instruction like this:
mov FactorString, 0
Interesting. Since FactorString is BYTE, shouldn't the assembler move a single zero BYTE into FactorString? If yes, is that by design?
Yes, MASM knows the defined type, so it encodes the instruction as:
mov byte ptr [ebp-64h],0
Quote from: MichaelW on January 25, 2008, 10:00:50 PM
Yes, MASM knows the defined type, so it encodes the instruction as:
mov byte ptr [ebp-64h],0
Thanxalot - I keep learning :toothy
Hi
I understand my errors in the codes that I posted before in different posts.
I am learning from them.
I am sorry for my errors.
Quote from: etow on January 26, 2008, 10:32:27 PM
I am learning from them.
I am sorry for my errors.
etow,
Making errors is normal, dont give up. No problem.
Did you solve your problem ? The limit ESI in the *** .While Factor <= Esi *** should be
the current Number. The current Number should be the Quotient when Remainder = 0. No ?
RuiLoureiro
Hey etow,
Please use Code Tags (http://www.masm32.com/board/Themes/default/help/posting.english.html#tags) when posting code. You can use the 'Insert Code' button or just put in the tags manually.
Yes, thanks
All my problems are solved.
Keep at it etow. :U
Here is my final code in zip file.
[attachment deleted by admin]
Etow,
I want to say that i am not a programmer and i am not young.
Are you a mathematics student ? You have some troubles with Math.
; This code should be:
.While Factor <= Esi ; while Factor less than or equal to (Number = Esi)
Mov Eax, Number ; set Eax = Number
Mov Ebx, Factor ; set Ebx = Factor
Cdq ; convert to double quad word or 64-bit long word
Div Ebx ; Eax = Eax / Ebx
Mov Quotient, Eax ; set Quotient = Eax
; Quotient = Number / Factor
; Mov Eax, Number ; set Eax = Number
; Cdq ; convert to double quad word or 64-bit long word
; Mov Ebx, Factor ; set Ebx = Factor
; Div Ebx ; Eax = Eax / Ebx, Edx contains the remainder
Do you believe you need to divide EDX:EAX 2 times, one to get
the quotient and the other to get the remainder ? Why ? And
then, why do you believe we need to do it one more time ? Why ?
This is the case here:
; This code should be:
Inc primeCounter ; primeCounter = primeCounter + 1
; generate PrimeFactor string by
; concatenating prime factors and
; adding them to PrimeFactor string
Mov Esi, Quotient ; set Esi = Quotient
Mov Number, Esi ; Esi = Number = Quotient
; Mov Edi, Quotient ; set Edi = Quotient
; Mov Number, Edi ; Edi = Number = Quotient
; Mov Eax, Number ; set Eax = Number
; Mov Ebx, Factor ; set Ebx = Factor
; Cdq ; convert to double quad word or 64-bit long word
; Div Ebx ; Eax = Eax / Ebx
; Mov Quotient, Eax ; set Quotient = Eax
; Quotient = Number / Factor
; Mov Remainder, Edx ; set Remainder = Edx
I try to explain: you want to get Factor *** While Factor <= Esi ***
where ESI is the Number to be factored.
Look at this example: Number=70, Factor=2 (at the begining). ESI=70.
Number Factor
Now, begin: 70 divided by 2 quotient=35 remainder=0
It means: 70 = 2 * 35 and means also that to get the next factor of 70
we need to get the factors of the Number=35
and we begin with the same Factor=2;
;.......................................................................
Now we want to get the factors of 35, so Number=35, ESI=35, Factor=2
Number Factor
Next step: 35 divided by 2 quotient=??? remainder=not 0
35 3 =??? =not 0
35 4 =??? =not 0
35 5 quotient=7 remainder= 0
It means: 35 = 5 * 7 and means also that to get the next factor
we need to use the Number=7 and the same Factor=5;
Then: 70 = 2 * 35 = 2 * 5 * 7 because 35 = 5 * 7
;.........................................................................
Now we want to get the factors of 7, so Number=7, ESI=7, Factor=5
Number Factor
Next step: 7 divided by 5 quotient=??? remainder=not 0
7 6 =??? =not 0
7 7 quotient= 1 remaider= 0
It means: 7 = 7 * 1 and means also that to get the next factor
we need to use the Number=1 and the same Factor=7;
ESI should be =1, too.
Then: 70 = 2 * 5 * 7.
Now stop because Factor is not less than or equal ESI (ESI=1 and Factor=7).
Isnt it?
RuiLoureiro
Hi RuiLoureiro,
Sorry I have not cleaned the code properly.
No, I do not have problems with math. I do well with math.
I think I have difficulty visualizing using assembly language instructions to get the math to work properly, that is all.
Here is the algorithm to get the prime factorization:
PrimeFactor = " "
Factor = 2
Do while (Factor <= Number)
Quotient = Number / Factor
Remainder = Number mod Factor
If (Remainder = 0) then
.If (primeCounter = 1) ; if primeCounter equals to 1
PrimeFactor = concat(PrimeFactor, Factor)
; insert the first prime factor to the PrimeFactor string
.ElseIf (primeCounter > 1) ; if primeCounter greater than 1
PrimeFactor = concat(PrimeFactor, " x ", Factor)
; concatenate additional prime factors to the PrimeFactor string
.EndIf
Number = Quotient
Quotient = Number / Factor
Remainder = Number mod Factor
Else
Factor = Factor + 1
EndIf
Loop
Here is my edited final code.
[attachment deleted by admin]
Sorry I forgot to mention how to increment primeCounter.
Here is the revised algorithm to do prime factorization:
primeCounter = 1
PrimeFactor = " "
Factor = 2
Do while (Factor <= Number)
Quotient = Number / Factor
Remainder = Number mod Factor
If (Remainder = 0) then
.If (primeCounter = 1) then ; if primeCounter equals to 1
PrimeFactor = concat(PrimeFactor, Factor)
; insert the first prime factor to the PrimeFactor string
.ElseIf (primeCounter > 1) then ; if primeCounter greater than 1
PrimeFactor = concat(PrimeFactor, " x ", Factor)
; concatenate additional prime factors to the PrimeFactor string
.EndIf
Number = Quotient
Quotient = Number / Factor
Remainder = Number mod Factor
primeCounter = primeCounter + 1
ElseIf
Factor = Factor + 1
EndIf
Loop
Reminder:
Number is a positive integer greater or equal to 2.
Another version of prime factorization but with a procedure call :
[attachment deleted by admin]