1

I have written the following code so far, which receives each digit of each number separately as inputs and stores them in the ax register (for instance, a five-digit number). However, when it comes to multiplying or dividing them, I have no idea how to get the right answer.

Here's how I received each of my numbers' digits:

 ;TITLE Multiply input with number then add them

.model small
.stack 100
.data
   
msg1 DB 13,10,"First input = $" ;
msg2 DB 13,10,"Second input = $"
msg3 DB 13,10,"Result = $"

num1 dw ?;user inputs
num2 dw ?

a dw 10000
b dw 1000
c db 100
d db 10


.code
main proc 
mov ax, @data
mov ds, ax

mov ah, 9h
lea dx, msg1
int 21h

mov ah, 1h
int 21h
sub al, 30h
mul a
mov num1, ax

mov ah, 1h
int 21h
sub al, 30h
mul b
add num1, ax

mov ah, 1h
int 21h
sub al, 30h
mul c
add num1, ax

mov ah, 1h
int 21h
sub al, 30h
mul d
add num1, ax

mov ah, 1h
int 21h
sub al, 30h
add num1, ax

; Getting the five digits of the first number
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • What is the maximum length of your numbers? The `IMUL` instruction can directly multiply two numbers of up to 64 bits (depending on the CPU architecture). – PMF Dec 28 '22 at 11:46
  • Product of multiplication two 16bit numbers is 32bit, you will obtain it in register-pair `dx:ax` after `mov ax,[num1]`, `mov cx,[num2]`, `mul cx`. – vitsoft Dec 28 '22 at 12:22
  • 1
    @PMF: This code is for 16-bit mode, as we can see from use of `int 21h` DOS system calls. So the widest product you can do in one instruction is 32x32 => 64-bit on a 386 in 16-bit mode, or 16x16 => 32-bit before that, like emu8086. – Peter Cordes Dec 28 '22 at 19:20

1 Answers1

1

Your worry about multiplying and dividing the inputs comes a bit too soon.

Incorrect input of the 5-digit number

For the 1st digit you first obtain a (hopefully) valid digit in the range [0,9] and you have it stored in the AL register. Then you use the mul a instruction to multiply this digit according to its rank in the whole number. That's fine except that a is defined a word (holding the value 10000), and so the multiplication will be a word-sized multiplication that multiplies AX by the source operand. The error is that only AL got a defined value and that you haven't made sure that AH is zero.

mov  ah, 01h
int  21h
sub  al, 30h
mov  ah, 0    ; (*)
mul  a
mov  num1, ax

You need the same correction for the 2nd digit because b too is a word-sized variable.

You don't have this problem for the 3rd and 4th digits as both the c and d variables are bytes that perfectly fit the byte-sized multiplication that you need.

The 5th digit poses a problem however. It doesn't require a multiplication (would be times 1), but you can't add AX to the num1 variable without making sure AH is zero.

mov  ah, 01h
int  21h
sub  al, 30h
mov  ah, 0    ; (*)
add  num1, ax

(*) Because AL is a small positive number, you could replace the 2-byte mov ah, 0 instruction by the 1-byte cbw instruction.

Multiplying 2 words

The word-sized multiplication will multiply AX by its word-sized source operand. The product will be in the pair of registers DX:AX.

mov  ax, num1
mul  num2        ; -> AX is product (if you can ignore DX)

Dividing 2 words

The word-sized division will divide DX:AX by its word-sized source operand. The quotient will be in the AX register and the remainder in the DX register.
It's this double-length dividend DX:AX that is often overlooked! You need to zero DX before doing the division:

mov  ax, num1
xor  dx, dx
div  num2        ; -> AX is quotient

From you msg3, I see that you will want to display the results. Next Q/A explains that in some detail: Displaying numbers with DOS.

There's also Inputting multi-radix multi-digit signed numbers with DOS in case you should need a more powerful number input.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76