/sigh
keep smashing my head on the desk with this one :dazzled:
I have to calculate powers recursively for this one: x^y. But it's a specific way the teacher wants us to do it. we have to have 2 procedures - one that is an input procedure that gets passed the address of 2 memory variables, and the other one is the actual recursive procedure that does the calculation. The way he wants us to do the calculation is:
(assume n2 is the exponent and n1 the base). If n2 is even then return power(n1*n1, n2 >> 1) else return n1*power(n1 * n1, n2 >> 1)
I can do this procedure the normal way by looping down n2 to calculate... but alas this is not what he wants.
Here is what I have now:
TITLE MASM Template (main.asm)
;includes
INCLUDE include\masm32rt.inc
.data
TWO SDWORD 2
base SDWORD 0 ;our base
exponent SDWORD 0 ;exponent
product SDWORD 1 ;answer is stored here
.code
;------------------------------------------------------------------------
;This is our recursive procedure that constantly calls itself to multiply
;------------------------------------------------------------------------
power PROC uses edx, n1:SDWORD, n2:SDWORD
print "n2 & n1 & product: "
print str$(n2)
print " "
print str$(n1)
print " "
print str$(product),13,10
mov edx,0 ;zero out edx for division
cmp n2,0 ;compare the exponent to 0, if its zero we are done
jle stop ;goto the return statement
mov eax,n2 ;move exponent to eax
IDIV TWO ;divide by TWO (2)
cmp edx,0 ;cmp the remainder to 0
je L1 ;if it is zero then its even so jump to L1
mov eax,n1 ; else copy the current product to eax
IMUL n1 ;multiply it by n1 which is the base
IMUL n1 ;multiply it again as per the project
mov product,edx ;product is in edx and move that back to product
SAR n2,1
Invoke power,n1,n2
jmp stop ;skip the label
L1:
mov eax,n1
IMUL n1 ;edx = eax * n1
mov product,edx ;move product into product from edx
SAR n2,1
Invoke power,n1,n2
stop:
RET
power ENDP
;-------------------------------------------
;Our procedure to obtain input from the user
;-------------------------------------------
getInput PROC n1:PTR SDWORD, n2:PTR SDWORD
mov n1, sval(input("Enter the integer base: "))
mov n2, sval(input("Enter the integer exponent: "))
mov ebx,n1
mov product,ebx
cmp n2, 0 ;check our exponent if it is negative get the absolute value
jl getABS
Invoke power, n1, n2
RET
getABS:
NEG n2
Invoke power, n1, n2
RET
getInput ENDP
main PROC
Invoke getInput,Addr base,Addr exponent
print "Answer: " ;print our answer
print str$(product),13,10
inkey
exit
main ENDP
END main
there are some print statements in there to help troubleshoot. For some reason product is being zeroed out. I did this in java because I was unfamiliar with the shifting and the effect it had on the project. Here it is if it helps anyone:
import java.util.Scanner;
public class AsmProj3test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int base;
int exponent;
int answer;
System.out.print("Enter base: ");
base = input.nextInt();
System.out.print("Enter exponent: ");
exponent = input.nextInt();
if(exponent < 0)
Math.abs(exponent);
answer = power(base,exponent);
System.out.println("Answer is: " + answer);
}
public static int power(int n1, int n2)
{
if(n2 <= 0)
return 1;
if(n1 % 2 == 0)
{
return power(n1*n1, n2>>>1);
}
else
return n1*power(n1*n1,n2>>>1);
}
}
So i essentially need a way to transfer the power function over to assembly. Help please! Thanks! :cheekygreen:
The product is not in EDX
; x = n1**abs(n2)
mov esi,1 ; x = 1
mov eax,n2
cdq ; ABS(n2)
xor eax,edx
sub eax,edx
jz label_30 ; is zero, n1**0 = 1
mov edi,n1 ; y = n1
; eax = abs(n2)
label_10:
test al,1 ; Is LSB set
jz label_20 ; No
imul esi,edi ; x = x * y
label_20:
shr eax,1
jz label_30 ; Continue if non zero, else exit early
imul edi,edi ; y = y * y
jmp label_10
label_30:
; esi = x = n1**abs(n2)
ahhh well your code went over my head. I changed it so eax is going into product instead of edx. I don't think the teacher really cares about the product becoming a 64 bit answer. I don't even know what you did :toothy
At what point do i get to
if(n1 % 2 == 0)
{
return power(n1*n1, n2>>>1);
}
else
return n1*power(n1*n1,n2>>>1);
?
You understand that it should be N2 % 2 right? Not N1
if(n2 % 2 == 0)
I'm not doing it recursively, but by powers of 2 in a loop. Achieves the same thing.
test al,1 ; Is LSB set, equivalent to if ((n2 % 2) == 0)
jz label_20 ; No, remainder of EAX/2 = 0
TITLE MASM Template (main.asm)
;includes
INCLUDE \masm32\include\masm32rt.inc
.code
;------------------------------------------------------------------------
;This is our recursive procedure that constantly calls itself to multiply
;------------------------------------------------------------------------
power PROC uses edx, n1:SDWORD, n2:SDWORD
mov eax,1 ; n1**0 = 1
mov edx, n2 ; move exponent to edx, edx = n2
cmp edx, 0 ; compare the exponent to 0, if its zero we are done
jle stop ; goto the return statement
mov eax, n1 ; eax = n1
imul eax, eax ; eax = eax (n1) * eax (n1), edx preserved
shr edx,1 ; edx = n2 >> 1, carry = n2 % 2
jnc L1 ; if it is zero (no carry) then its even so jump to L1
Invoke power,eax,edx ; power(n1*n1, n2 >> 1)
imul eax, n1 ; * n1
jmp stop ; return(n1 * power(n1*n1, n2 >> 1))
L1:
Invoke power,eax,edx ; return(power(n1*n1, n2 >> 1)
stop:
ret ; returns answer in eax
power ENDP
;-------------------------------------------
;Our procedure to obtain input from the user
;-------------------------------------------
main PROC
LOCAL n1:SDWORD
LOCAL n2:SDWORD
mov n1, sval(input("Enter the integer base: "))
mov n2, sval(input("Enter the integer exponent: "))
cmp n2, 0 ;check our exponent if it is negative get the absolute value
jge positive
NEG n2 ; n2 = -n2
positive:
Invoke power, n1, n2
; answer in eax = power(n1, abs(n2))
push eax
print "Answer: " ;print our answer
pop eax
print str$(eax),13,10
inkey
exit
main ENDP
END main
alright thanks. yeah that was a typo for the java app i wrote up. Didnt even notice because the input i was putting in was still giving me the right answer.
clive
According to your latest posted procedure, what result would it output for an input such as 27?
It seems that you would first re-enter the procedure with eax=22 and edx=3,
then with eax=24 and edx=1,
then with eax=28 and edx=0,
which would exit with eax=1 and return to the imul eax, n1 instruction where you would multiply by 2,
then return to that instruction twice more to finally exit with eax=23.
Seems to be working as designed here.
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 7
Answer: 128
Press any key to continue ...
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 0
Answer: 1
Press any key to continue ...
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 1
Answer: 2
Press any key to continue ...
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 2
Answer: 4
Press any key to continue ...
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 3
Answer: 8
Press any key to continue ...
C:\MASM>pp
Enter the integer base: 2
Enter the integer exponent: 16
Answer: 65536
Press any key to continue ...
00000000 _power@8:
00000000 55 push ebp
00000001 8BEC mov ebp,esp
00000003 52 push edx
00000004 B801000000 mov eax,1
00000009 8B550C mov edx,[ebp+0Ch]
0000000C 83FA00 cmp edx,0
0000000F 7E1E jle loc_0000002F
00000011 8B4508 mov eax,[ebp+8]
00000014 0FAFC0 imul eax,eax
00000017 D1EA shr edx,1
00000019 730D jnb loc_00000028
0000001B 52 push edx
0000001C 50 push eax
0000001D E8DEFFFFFF call _power@8
00000022 0FAF4508 imul eax,[ebp+8]
00000026 EB07 jmp loc_0000002F
00000028 loc_00000028:
00000028 52 push edx
00000029 50 push eax
0000002A E8D1FFFFFF call _power@8
0000002F loc_0000002F:
0000002F 5A pop edx
00000030 C9 leave
00000031 C20800 ret 8
Quote from: raymond on April 30, 2010, 03:46:48 AM
clive
According to your latest posted procedure, what result would it output for an input such as 27?
It seems that you would first re-enter the procedure with eax=22 and edx=3,
then with eax=24 and edx=1,
then with eax=28 and edx=0,
which would exit with eax=1 and return to the imul eax, n1 instruction where you would multiply by 2,
then return to that instruction twice more to finally exit with eax=23.
Not that it's my assignment, but 1 * 2^4 * 2^2 * 2, or 128
My bad. :red :red :red
Just realized that the "n1" on the stack changes with each iteration. Must be old age taking over. :eek
Nice work clive. :clap:
nah, Ray
you are good for another 2e+4 miles :bg
a little wear, but the tread is still good