0

The program will accept two numbers from the user and display the sum, product, and power (a^b) of those two numbers. Here is the catch, however...

The program MUST: Use an AddNumbers function Use that AddNumbers function in a MultiplyNumbers function Use that MultiplyNumbers function in a CalculatePower function

I cannot figure out how to find the Product of the two numbers by implementing the multiplication through addition function. I cannot grasp the logic behind it. I'm obviously doing something wrong, but I'm not sure what. (Please ignore the inefficiency of the code, I just want to know what I'm doing wrong as far as finding the product of the two)

My code so far..

INCLUDE Irvine32.inc
.data
str1 BYTE "Enter a positive integer: ",0
str2 BYTE "The sum is: ",0
str3 BYTE "The product is: ",0
str4 BYTE "The power result is: ",0

.code
main PROC

call GetInteger
call Crlf
mov eax, ebx
call AddNumbers

mov edx, OFFSET str2
call WriteString
call WriteInt
call Crlf
mov eax, 0
mov ecx, edi
call MultiplyNumber
mov eax, edx
mov edx, OFFSET str3
call WriteString
call WriteInt
call Crlf
call CalculatePower
mov eax, esi
mov edx, OFFSET str4
call WriteString
call WriteInt
call Crlf

exit
main ENDP

GetInteger PROC 
mov edx, OFFSET str1
call WriteString
call ReadInt
mov ebx, eax
call WriteString
call ReadInt
mov edi, eax
ret
GetInteger ENDP

CalculatePower PROC USES edi ebx 

mov ecx, edi
mov esi, 0
L2:

    call MultiplyNumber
    add esi, edx
    loop L2
    ret
CalculatePower ENDP

MultiplyNumber PROC USES ebx edi ecx

mov edx, 0
L1:
    mov edi, ebx
    mov eax, 0
    call AddNumbers
    add edx, eax
    loop L1
    ret
MultiplyNumber ENDP

AddNumbers PROC 

    add eax, edi

ret
AddNumbers ENDP

END main
rkhb
  • 14,159
  • 7
  • 32
  • 60
Bubz21
  • 15
  • 1
  • 4
  • 3
    Surely you've learned in school how multiplication relates to addition(?). To quote from wikipedia: _"The multiplication of two whole numbers is equivalent to the addition of one of them with itself as many times as the value of the other one; for example, 3 multiplied by 4 (often said as "3 times 4") can be calculated by adding 3 copies of 4 together"_. – Michael Sep 15 '14 at 05:37
  • 1
    It seems insane that multiplication can't simply use `mul/imul` instructions on x86 ... anyway, you can use [shift-add](http://stackoverflow.com/questions/2776211/how-can-i-multiply-and-divide-using-only-bit-shifting-and-adding) emulate it. – Brett Hale Sep 15 '14 at 07:26
  • A great deal of your difficulty in understanding is caused by the lack of commenting. If you will put a (meaningful, accurate) comment on each line of code you write, the lights will come on a lot faster – User.1 Sep 15 '14 at 09:21
  • A comment on each line? Comments are, IMO, only necessary if the code is hard to follow or does something non-standard. Such comments are useful. Putting a comment on each line would decrease the signal-to-noise ratio far too much, IMO. – Rudy Velthuis Sep 15 '14 at 15:43
  • Assembly code is already hard to follow, and taking away use of the mul instructions is pretty non-standard. It's also obvious that this is for educational purposes and not production. So for *this* situation, I would say there should be more comments than code. – iwolf Sep 15 '14 at 16:37

2 Answers2

0

Try this one. Your code is complicated to analyze because you have different loops in different procedures without initializing ecx again etc.

OPTION CASEMAP:NONE

INCLUDE Irvine32.inc

ExitProcess proto, dwExitCode:dword

.data
    str1 BYTE "Enter a positive integer: ",0
    str2 BYTE "The sum is: ",0
    str3 BYTE "The product is: ",0
    str4 BYTE "The power result is: ",0
    num1 DWORD 0
    num2 DWORD 0
    sum  DWORD 0
    prod DWORD 0
    pow  DWORD 0
    tmp  DWORD 0

.code
    main PROC

        mov edx, OFFSET str1    ;// Input
        call WriteString
        call ReadInt
        mov [num1], eax
        mov edx, OFFSET str1
        call WriteString
        call ReadInt
        mov [num2], eax

        call doSum              ;// Calculations
        call doMul
        call doPow

        mov edx, OFFSET str2    ;// Output
        call WriteString
        mov eax, [sum]
        call WriteInt
        call Crlf

        mov edx, OFFSET str3
        call WriteString
        mov eax, [prod]
        call WriteInt
        call Crlf

        mov edx, OFFSET str4
        call WriteString
        mov eax, [pow]
        call WriteInt
        call Crlf

        invoke ExitProcess, 0

    main ENDP

    doSum PROC              ;// Sum
        mov eax, [num1]
        add eax, [num2]
        mov [sum], eax
        ret
    doSum ENDP

    doMul PROC              ;// Multiply: Add num1 x num2 times
        xor eax, eax
        mov ecx, [num2]
        ADD_LOOP:
            add eax, [num1]
        loop ADD_LOOP
        mov [prod], eax
        ret
    doMul ENDP

    doPow PROC              ;// Power: Add num1 x num2 times and 
        mov eax, [num1]     ;// add result x num2 times till ebx=0
        mov [tmp], eax
        mov ebx, [num2]
        dec ebx
        POW_LOOP:
            xor eax, eax
            mov ecx, [num1]
            ADDPOW_LOOP:
                add eax, [tmp]
            loop ADDPOW_LOOP
            mov [tmp], eax
            dec ebx
        jnz POW_LOOP
        mov [pow], eax
        ret

    doPow ENDP

END main

Modified version with call of addition proc from multiplication and power proc:

OPTION CASEMAP:NONE

INCLUDE Irvine32.inc

ExitProcess proto, dwExitCode:dword

.data
    str1 BYTE "Enter a positive integer: ",0
    str2 BYTE "The sum is: ",0
    str3 BYTE "The product is: ",0
    str4 BYTE "The power result is: ",0
    num1 DWORD 0
    num2 DWORD 0
    sum  DWORD 0
    prod DWORD 0
    pow  DWORD 0
    tmp  DWORD 0

.code
    main PROC

        mov edx, OFFSET str1    ;// Input
        call WriteString
        call ReadInt
        mov [num1], eax
        mov edx, OFFSET str1
        call WriteString
        call ReadInt
        mov [num2], eax

        mov eax, [num1]         ;// Calculations
        mov ebx, [num2]
        mov ecx, 1
        call doSum          
        mov [sum], eax
        call doMul
        call doPow

        mov edx, OFFSET str2    ;// Output
        call WriteString
        mov eax, [sum]
        call WriteInt
        call Crlf

        mov edx, OFFSET str3
        call WriteString
        mov eax, [prod]
        call WriteInt
        call Crlf

        mov edx, OFFSET str4
        call WriteString
        mov eax, [pow]
        call WriteInt
        call Crlf

        invoke ExitProcess, 0

    main ENDP

    doSum PROC              ;// Sum: (add ebx to eax) * ecx times
        SUM_LOOP:           ;// when ecx = 1 => simple addition a+b
        add eax, ebx
        loop SUM_LOOP
        ret
    doSum ENDP

    doMul PROC              ;// Multiply: Add num1 x num2 times
        xor eax, eax
        mov ebx, [num1]
        mov ecx, [num2]
        call doSum          ;// call Sum proc
        mov [prod], eax
        ret
    doMul ENDP

    doPow PROC              ;// Power: Add num1 x num2 times and 
        mov eax, [num1]     ;// add result x num2 times till end
        mov [tmp], eax
        mov esi, [num2]
        dec esi
        POW_LOOP:
            xor eax, eax
            mov ebx, [tmp]
            mov ecx, [num1]
            call doSum      ;// Call Sum proc
            mov [tmp], eax
            dec esi
        jnz POW_LOOP
        mov [pow], eax
        ret

    doPow ENDP

END main
f6a4
  • 1,684
  • 1
  • 10
  • 13
  • This example is ok, but the problem statement specifically mentions that the AddNumbers function is to be called by the multiply and power functions. I would just have the functions return the result in eax. Since only two values are needed for input, esi and edi could be used as register inputs. Microsoft's fastcall model uses ecx and edx, but since ecx can be used for looping, using esi and edi would mean less register copying. – rcgldr Sep 16 '14 at 01:49
  • Guys, thank you for your comments and I will take them with me as I move forward in my course. Also, f6a4, thank you so much for that solution. It wasn't exactly how I needed the program done, but it gave me a solution to work with and helped me figure out what I was doing wrong and what to look for next time, Thank you! PS- I noticed that 'xor' is a very important part of the program, removing it diminishes the product function. I'm not exactly sure why this is (still a noob at this). Any explanation? – Bubz21 Sep 16 '14 at 02:16
  • @rcgldr: You're right, I've added a version that calls the sum proc from mulitplication and power proc. And yes, it would be better using more registers and less memory addressing (I would add a macro as well), but this is for learning purposes and the code should be understandable for a beginner (hopefully). – f6a4 Sep 16 '14 at 06:31
0

This one is a lot easier trust me. I just dont know how it works hehehe.

 %include "asm_io.inc"
segment .data
    prompt db "Enter first num ",0
    prompt1 db "Enter second num ",0
    prompt2 db "Equals ",0
segment .bss
    input1 resd 1
    input2 resd 1
segment .text
    global _asm_main
_asm_main:
    enter 0,0
    pusha

    mov eax, prompt
    call print_string

    call read_int
    mov [input1], eax

    mov eax, prompt1
    call print_string

    call read_int
    mov [input2], eax

    mov eax, prompt2
    call print_string

    mov eax, [input1]
    mov ebx, [input2]
    mov ebx, eax
    mul ebx
    call print_int

popa
mov eax,0
mov ebx,0
leave
ret