Вы находитесь на странице: 1из 7

University of the East

College of Engineering
Caloocan Campus
Computer Engineering Department

Research
Theories on Arithmetic Operations
in Assembly Language
Computer Lecture 3
COE413 1M ~ W
9:00am-10:30am

Submitted By: Argelo Royce P. Bautista


Submitted to: Prof. Paraluman Sim
Date: October 12, 2010

I.

Introduction

From elementary up to real life work, basic arithmetic operations are always used. Even
from the ancient times, our ancestors are aware of this branch of mathematics and its
significance. Arithmetic is also the primary reason why the development of computers has been
started, to perform arithmetic calculations faster and more efficient.
Unlike us, who performs arithmetic operations in the normal or decimal number system,
the computer performs these operations in binary (base-2) number system. The result, when
converted back, is still the same as if the operation was performed in decimal number system.
Ex:
In decimal: 4+5=9
In binary (4 bit)
4=0100
5=0101
0100
+0101
1001 = 9
For ease and spatial concerns, these binary values are represented in hexadecimal values in
assembly language codes.
In codes the values that we encounter are in hexadecimal however if we associate user
inputs in the program, the program will not treat the user inputs as absolute binary or
hexadecimal values, it considers the input as an ASCII character where each character has an
equivalent value in the AL register (0=30h and 9=39h).
For addition and subtraction we directly add or subtract the ASCII values before using an
adjustment for the correct ACII value of the result (using the OR command) but for division and
multiplication, we must first convert the ASCII values to their absolute binary value (by means of
the command AND) before proceeding with the operation, and another adjustment and
conversion for the printing of the result.
The assembly language does not permit us to proceed with arithmetic operation
with direct reference to the declared memory addresses, hence we move values from memory
address to register from time to time.

II.

Review of Data Sizes and Registers

A digit of binary data is called a bit. Four digits of binary data is called a nibble which
also defines a digit of Hexadecimal data. The most important is the byte which is actually an 8
digit binary data or a 2 digit Hexadecimal data. This two digit hexadecimal data is enough to
contain every entry in the ASCII table including the codes of the number 0-9. A byte is also the
data that the lower or higher half of the register can contain. Other data types include words (2
bytes) and double word (4bytes). A word could occupy a whole register (Ex. AX register) while a
double word could occupy an extended register (Ex. EAX Register). Hence we could say that
the maximum data size that the result could be is a double word.
Data size is important for signed values because when a byte reaches a binary value of
0111 1111 or a hexadecimal value of 7F, anything that is higher would be negative in value.
However by extending the byte into a word we could increase the limits of the positive values
from 127 to 32,767. We could extend the AL register from a byte to a word by using the
command CBW, but this uses the AH register as well, hence the whole AX register will be used
to contain the word data.
Before CBW:
AH
AL
Xx
80h
After CBW:
AH
AL
00
80H
For an unsigned data, the numeric value is still the same, but for a signed value the
numeric value changes from -127 to positive 128. The ax register could further be extended into
a double word by using the command CWD which uses the DX:AX register combination,
alternatively we could use the CWDE where, instead of using the DX, it extends the value of AX
to EAX (Duplicated bit capacity of AX). Lastly we could further extend doubleword data to
quadword by using CDQ, where, like CWD, it uses EDX:EAX Combination. The quadword data
size might denote a data size limitation but there are techniques that can be used (like byte by
byte or digit by digit processing) to process data of any length.
When dealing with user entered values we need to declare memory addresses to
contain the number strings. This memory address could be declared as a byte, word, double
word, quadword or even ten bytes; once that a memory address is declared with a data size, the
operation will follow the data size. Hence we could say that words and double words are
shorthands for dealing with two digit to four digit numerals. But for numerals of any length
(which is what we are dealing with the user inputs) it is advisable to use the byte data size so
that we could create an algorithm that performs arithmetic operations byte by byte (in our sense,
the algorithm is more like performing an arithmetic operation digit by digit just like an elementary
student).
This technique calls for almost all the presence of the registers: DI and SI to contain the
inputs of the user, AX & DX to do the operation and BX to contain the result. These registers
together with the CX constitutes the loping statements which continuously performs the
algorithm as the computer moves from one digit to another.

III.

Arithmetic Commands

Like what mentioned earlier, there are two types of numerical data with respect to the
capacity of the computer: Signed data and unsigned data. TASM commands are designed to
deal with these two types of data, however treatment for signed data is different from unsigned
data. Unsigned data is performed as is while signed data have a set of command specially for
dealing with them. Signed data can also be detected by the number one on the last bit of the
binary code. This condition would be the basis of coding a separate algorithm for signed data.
Here are the commands that could be used for both signed and unsigned data:
ADD -the basic addition command. This command cannot be only used in multiple
increments, it can also be used, just like the command itself denotes, in addition operations
between registers.
ADC -This is the Add with carry command. In the ADD command when we add two binary
number bytes lets say 99h and 99h, the result will be 2, since when we convert 9 to binary and
add them accordingly: 1001 1001 + 1001 1001 = 1 0011 0010. The left most bit will not be
included in the result because the results data size is the same as the size of the
register/memory address that the second value was added to. If the bytes are added, the sum
will not fit in the byte size.
Usually this problem arises in algorithms involving byte by byte addition. If we add byte
using ADC command it will set the carry flag whenever a bit will not fit in the byte size and set
back the carry flag to zero when it performs the next addition operation along with the carried
bit.
SUB - Like what the command says it performs simple subtraction of binary data, when the
subtrahend is greater than the minuend the command will return a twos compliment result.
Hence for the absolute value of the negative value we need to reverse the bits and add 1.
SBB - This is the Subtract with borrow command, like the ADC command it also sets the carry
flag whenever the subtraction needs to borrow one from an adjacent bit. When it performs the
next subtraction it will additionally subtract 1 from the minuend and set the carry flag back to
zero.
Note: The addition and subtraction commands can be done between registers, register
and memory, memory and register, register and immediate value and memory and immediate
value.
Here are commands that should only be used on unsigned data:
MUL - This is the command for unsigned multiplication of binary data. Unlike ADD and SUB,
where the commands needs two references to be processed, the MUL command need only
one, it then multiplies the reference to the AL register and stores the product to the whole AX
register, that is if the reference is a byte. For word, the command will multiply the AX register
and store the higher part of the product in the DX register, and the lower part of the product in
the AX register. For doubleword reference, the command multiplies the EAX and the product is
stored in the EDX and EAX in the same manner as to word multiplications.
DIV
- This is the command for unsigned division, it needs a register or a memory address to
proceed with operation. The specified will be used as a divisor. When the divisor is a byte, the
command will use the AX as the dividend and it will store the quotient in the AH register and the
remainder in the AL register. When the divisor is a word, the command will use the DX:AX pair
as the dividend, where DX contains the higher part of the dividend and AX contains the lower
part of the dividend, It will then store the quotient in the DX register and the remainder in the AX
register. And when the divisor is a doubleword the dividend is the combination of EDX:EAX and
the quotient will be stored in EDX and the remainder will be in the EAX.

Note: There is no command in assembly language that will return a quotient with a
decimal point. Hence, for a program to yield a quotient with decimal parts another algorithm has
to be utilized.
Another way of dividing in Assembly is by performing successive subtraction. That is compare
the dividend to the divisor, if the dividend is greater than the divisor, subtract the divisor from the
dividend and increment the quotient, repeat until the dividend is less than the divisor because
on that point what is left in the divisor is the remainder.
When using this method and the dividend is in the DX:AX pair, compare the lower part
only when the higher part is zero and after the sub instruction insert SBB DX, 00. At this method
of division, when the dividend is very large and the divisor is very small, the process might
involve a large number of recursion and process time might increase.
Here are commands that are especially for signed data:
IMUL - this command is the multiplication command that is for signed values. This command
takes in consideration the last bit of data in the numeric input as a sign flag (1 is negative) and
multiplies only the remaining bits.
IDIV - Similarly this is the command for signed division, like IMUL it also considers the last bit
and uses the rest of the value as the dividend and the divisor.
Note: The DIV and IDIV operations assume that the quotient is significantly smaller than
the original dividend, as a consequence, the operation can easily cause an overflow with very
small divisors; when it does an interrupt occurs, with unpredictable results. For example, when
we divide a word by one, the quotient is the word itself bu the contents of the word cannot
possibly fit in a lower or higher half of a register; The quotient exceeded available bit space for a
quotient.
A simple rule is that the divisor must be greater than the higher part of the dividend (AH
for byte, DX for word and EDX for a doubleword). In cases where the divisor is less than the
higher part of the dividend, it is advisable to use the successive subtraction.
NEG - The NEG or Negate command reverse the sign of a binary value from positive to
negative vice versa in a register or a memory address. It reverses the bits, just like not and then
adds 1 for proper twos compliment notation.
Note: The NEG command cannot work on doubleword using a combination of DX & AX
because when NEG is used on both registers it will add 1 on both register. Instead we use NOT
command, ADD 1 to AX and ADC to DX.

IV.

Dealing with user inputs

The natural data format for arithmetic on a computer is binary, however, much of the
data that must be processed by the program is in decimal and the input from the keyboard and
the output on the monitor, numerals, are coded as ASCII characters.
As seen from the introduction a common characteristic of all ASCII numerals is that they
take up the hexadecimal codes from 30h(0) to 39h(9). From this detail four adjustment
commands were made, these commands along with the AND and OR commands can be
programmed to reduce ASCII codes to binary, adjust the binary code after the operation and
restore the ASCI representation of the process result.
The ASCI Adjustment commands are:
AAA - ASCII Adjust after addition. If we consider the ASCII numbers 8(38h) and 4(34h_ and
used the add command, the sum would be 6Ch which is neither a correct ASCII nor a correct
binary value. However if we ignore the left most 6, and add 6 to the right most hex it will yield
12, which is then the correct value in terms of decimal numbers. Why add 6? Because that is
the difference between hexadecimal(16) and decimal(10). Although a little over simplified, it
does indicate the way in which AAA performs its adjustment.
The AAA operation checks the right most hex digit(4bits) of the AL register. If the digit is
between A & F or the auxiliary carry flag (AF) is 1, the operation adds 6 to the AL register, adds
1 to the AH register, and sets the carry flag (CF) and the auxiliary carry flag (AF) to 1. In all
cases, AA clears the left most digit of the AL to zero. In the example, when we adjust 6Ch
accordingly, the AL will contain 72h and AH will contain 1. The left most digit of AL (7) will be
cleared hence the result in the AX register will be 0102h. to restore the ASCII representation,
simply insert 3s in the left most hex digits of the AH and AL to get 3132h or (when printed in the
monitor) 12. We utilize the OR command for this function (OR AX, 3030H).
AAS - ASCII adjustment after subtraction works just like AAA. AAS checks the right most hex
digit of the AL, if the digit is between A and F or the auxiliary carry flag is 1, the operation
subtracts 6 from the AL, subtracts 1 from the AH, and sets the auxiliary (AF) and carry (CF)
flags . In all cases, AAS clears the left most hex digit of the AL to zero.
AAM - ASCII Adjust after multiplication corrects the result of multiplying ASCI data in the AX
register. However, you must first clear the 3s in the left most hex digit of each byte. Because the
adjustment is only one byte at a time, you can multiply only 1 byte fields and have toi perform
the operation repetitively in a loop. This can only be used in unsigned multiplication (MUL
command).
AAM divides the AX by 10(0Ah) and stores the quotient in the AH and the remainder in
the AL.
Example: 5*9
9 in ascii is 39h
5 in ascii is 35h
Code:
Mov al, 39h ;Placing the values in the registers
Mov cl, 35h ;
And al, 0Fh ; we utilze the AND command to remove the 3s
And cl, 0Fh ; AL now contains 09h, and CL now contains 05h
Mul cl
; multiplies AL by Cl, and stores product in AX (002Dh)
Aam
; performs adjustment
Or ax, 3030h ; restores ASCII representation
The MUL operation generates 45(002Dh) in AX, AAM divides this value by 10, yielding a
quotient of 04 in the AH and a remainder of 05 in the AL, the OR instruction inserts 3s back on
the left most hex digits restoring the ASCII codes of the numerals.

AAD - ASCII Adjustment BEFORE division provides a correction of an ascii dividend prior to
dividing. Just as with AAM, you must first clear the leftmost 3s from the ASCII bytes,use the
adjustment command, proceed with divison and then use the OR command to restore the ASCII
representation. AAD allows for a 2-byte dividend in the AX> the divisor can only be a single byte
containing 01 to 09. AAD multiplies the AH by 10, adds the product to the AL, and clears the AH.
The result will be the hex representation of the quotient.
These commands only deals with unsigned user inputs, techniques varies when signed
numbers are at stake. Mainly the use of the negate command will be involved with the signed
numbers along with series of conditional jumps. The idea is to use the conditional jumps as a
detector of the presence of signed numbers so that the program could perform the appropriate
arithmetic of unsigned data and when the result is ready, the program could just negate the sign
again to turn it back to negative value.

Вам также может понравиться