1

I have already coded half of the program. The problem is I don't know how to code math operation part is raise m to the power of n (m^n). So, any advise for me as a beginner?

.MODEL SMALL

.DATA

greet   db 13,10, "Welcome to Simple Calculator: Raise m to the power n. $"
msg1    db 13,10, 0AH,0DH,"Please enter integer (m:-99 to 99): $"
m       db 3,4 dup(?)
msg2    db 10,13, 0AH,0DH,"Please enter power (n:1 to 9): $"
n       db 3,4 dup(?)
total   db 10,13, "Answer: $"


.CODE

START:

mov ax, seg greet
mov ds, ax
mov dx, offset greet
mov ah, 09h     ;Display message
int 21h 

mov ax, seg msg1
mov ds, ax
mov dx, offset msg1
mov ah, 09h
int 21h         ;Print a message

mov ah, 0ah
mov dx, offset m
int 21h         ;Get 'm' value


n_POWER:

mov ax, seg msg2
mov ds, ax
mov dx, offset msg2
mov ah, 09h
int 21h         ;Print a message

mov ah, 0ah
mov dx, offset n    ;Get 'n' value
int 21h

mov ax, m
mov n, ax
mul ax, n
mov total, n

finish:
mov ah, 09h ;Display message
int 21h

mov ax,4c00h    ;Return control to DOS
int 21h         
end start

Also, how can I get the negative input from the user (eg. -99) ?

user2264387
  • 13
  • 1
  • 1
  • 4
  • do i need to use "JMP" commands? – user2264387 Apr 10 '13 at 04:08
  • Related: [function Power(x,y) in assembly ia32 max 32 bit](https://stackoverflow.com/q/53341606) for the standard O(log2(n)) integer power algorithm using multiplying and shifting. (Like for implementing multiply in terms of shift-and add, but exponentiation in terms of multiply.) – Peter Cordes Jan 14 '22 at 17:36

2 Answers2

3

You can either repeat the multiplication as in:

int result = 1;  while (exp-->0) { result *= base; } return result;

or, you can / should treat the exponent in it's binary representation:

5^13 = 5^(0b1101) = 1*(5^1)*(5^4)*(5^8)

One can thus repeatedly square a copy of the base 5: 5 -> 25 -> 625 -> 390625 and multiply those terms that have a corresponding bit set in the binary representation of the exponent.

This may be overkill for 16-bit arithmetic, but it'll be handy if your professor asks you to perform a modular exponentation instead (as used in asymmetric cryptography).

Both methods require using conditional jumps:

to conditionally repeat cx number of operations one simply does:

         mov cx, 13
label:   nop  // put your block of code here
         nop
         loop label;  // The instruction at label will be executed 13 times
         // and cx will end up being zero

To test a bit being set, one can do

         mov dx, 13      ;; let's have the exponent here
label:   test dx, 1      ;; check if the first bit is zero
                         ;; test performs bitwise _and_ between the operand
                         ;; and sets ZERO flag (among other things)
         jz   notset     
         nop             ;; insert here the statements to be executed
                         ;; when the bit in the exponent is set
notset:  shr dx, 1       ;; shift out the least significant bit -- this also
                         ;; sets the ZERO_FLAG if dx goes to zero
                         ;; (and it eventually does)
         jne label;      ;;

btw. JNE == Jump if Not Equal also tests for zero flag. It's synonymous to Jump if Not Zero.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
  • yes, thank you for your help. But, why i must use looping 13 times? can '13' be replaced by 'n' for power? – user2264387 Apr 10 '13 at 08:42
  • 1
    Yes, you can and should replace the constant with your variable. Also you should fill in the instructions performing the multiplication and squaring. This is by no means a complete block of code to be copy-pasted, as this would defeat the purpose of learning. – Aki Suihkonen Apr 10 '13 at 09:07
  • if i want to put input for eg. '-99' , how should i do? i must convert those thing in binary? or any other way? – user2264387 Apr 10 '13 at 10:17
  • Please make that a separate question. (Or even preferably try the find an assembler primer, which has a chapter about integer representation, base conversions and input/output of numbers). I'm sure the FAQ section of assembler tag in SO is also full of duplicates. – Aki Suihkonen Apr 10 '13 at 10:32
1

Computing integer powers is just a series of multiplications. For example, 5^2 == 5*5, 2^3 == 2*2*2, and so on.

Hence, a simple multiplying loop will suffice:

mov bx,5   ; m
mov cx,3   ; n
mov ax,1   ; Initial result, i.e. m^0
power:
    jcxz power_done
    mul bx
    loop power
power_done:
; ax now contains m^n

Note that my example code doesn't handle cases where the result grows larger than 16 bits (except implicitly on the last iteration). It also doesn't handle negative values for m. I'll leave it as an exercise for you to look up the instruction set reference for ways to fix those things if you need them.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • Why do you need jcxz (and if it's for generic case, why is it inside the loop block?) – Aki Suihkonen Apr 10 '13 at 06:26
  • To make a self-contained loop block which handles all inputs >= 0. The question wasn't about the fastest way of calculating powers (in that case the OP should just use a modern C/C++ compiler and call it a day). – Michael Apr 10 '13 at 06:34
  • mean that, i can substitute constant '5' with 'm'? – user2264387 Apr 10 '13 at 07:21
  • Wait. `m` and `n` are input buffers for `int 21h/0Ah`. Input text starts at `n + 2` and `m + 2`... and it's a text representation of a number, not a number you can do arithmetic on. – Frank Kotler Apr 10 '13 at 07:52
  • @FrankKotler: Correct. `m` and `n` are assumed to be integers, since the question was how to perform the `power` operation. If the inputs are strings they'd have to be converted to integers beforehand, but that would be a separate question. – Michael Apr 10 '13 at 08:07
  • `jcxz` doesn't need to be inside the loop. See [Why are loops always compiled into "do...while" style (tail jump)?](https://stackoverflow.com/q/47783926) for normal loop structure to handle the case where the count may be zero. – Peter Cordes Jan 14 '22 at 17:37