Assembly language: summing decimal numbers of arbitrary length

1. Question requirements

Enter the sum of two decimal numbers of any length (within 20 digits) on the keyboard. Use “-” to identify negative numbers. Positive numbers can be left unsigned or added with a “+” sign.

(Assembly language programming environment used: Masm for Windows integrated experimental environment 2012.5)

2. Question Analysis

This question requires the addition of decimal numbers of any length. Compared with the addition of assembly instructions, the number of addition digits in this question is large and the number of digits and the sign is uncertain, and the carry situation that needs to be considered is more complicated. Therefore, based on the above analysis, using traditional assembly instruction addition and subtraction may not be able to meet the requirements of this question, and it is necessary to combine resources such as memory to achieve the question requirements.

3. Ideas and flow charts

Since the number of addition and subtraction data required by the question is too long, we decided to read the data from the memory bit by bit to the register for addition and subtraction and record whether there is a carry or a borrow. First, when receiving the input data, it is judged whether the digits of the two data are the same. If they are the same, 30H will be subtracted from the ASCII code value and stored. If they are not the same, zeros will be added in front of the data with smaller digits. Then judge the sign. If they have the same sign, add the absolute values of the two data and get the sign. If they have different signs, subtract the absolute values of the two data and get the sign.

4. Program code

DATAS SEGMENT
    ;Enter data segment code here
    BUF1 DB 30
         DB?
         DB 30 DUP('#')
         DB '$'
    BUF2 DB 30
         DB?
         DB 30 DUP('#')
         DB '$'
    BUF3 DB 30 DUP(?),'$'
    BUF4 DB 30 DUP(?),'$'
    BUF0 DB 30 DUP('$'),'$'
    message1 DB 'Please input the first number:','$'
    message2 DB 0AH,0DH,'Please input the second number:','$'
    message0 DB 0AH,0DH,'Result:','$'
    message_fu DB '-','$'
    message_zheng DB ' + ','$'
DATAS ENDS

STACKS SEGMENT
    ;Enter stack segment code here
    DB 256 DUP(?)
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOVAX,DATAS
    MOVDS,AX
    ;Enter snippet code here
    ;Enter addend 1
    LEA DX,message1
    MOVAH,09H
    INT 21H
    LEA DX,BUF1
    MOVAH,0AH
    INT 21H
    ;Enter addend 2
    LEA DX,message2
    MOVAH,09H
    INT 21H
    LEA DX,BUF2
    MOVAH,0AH
    INT 21H
    
    ;process addends
    LEA SI,BUF1
    INC SI
    MOV AL,[SI]
    LEADI,BUF2
    INC.DI.
    MOVAH,[DI]
    .IF AH>AL
    MOV BH,AH
    MOVBL,AL
    SUB AH,AL
    MOV CH,0
    MOVCL,AH
    LEA SI,BUF1
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF3

    AGAIN1: MOV AL,0
    MOV[DI],AL
INC.DI.
LOOP AGAIN1
MOV CH,0
MOVCL,BL
DEC CL
AGAIN2: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN2
LEA SI,BUF2
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF4
    MOV CH,0
MOV CL,BH
DEC CL
AGAIN3: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN3
    .ELSEIF AH<AL
    MOVBL,AH
    MOV BH,AL
    SUB AL,AH
    MOV CH,0
    MOVCL,AL
    LEA SI,BUF2
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF4
    AGAIN4: MOV AL,0
    MOV[DI],AL
INC.DI.
LOOP AGAIN4
MOV CH,0
MOVCL,BL
DEC CL
AGAIN5: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN5
LEA SI,BUF1
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF3
    MOV CH,0
MOV CL,BH
DEC CL
AGAIN6: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN6
.ELSE
MOVBL,AL
MOV BH,AH
LEA SI,BUF1
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF3
MOV CH,0
MOVCL,AL
DEC CL
AGAIN55: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN55
LEA SI,BUF2
    INC SI
    \t
    INC SI
    \t
    INC SI
    LEADI,BUF4
    MOV CH,0
MOVCL,AH
DEC CL
AGAIN66: MOV AL,[SI]
SUB AL,30H
MOV[DI],AL
INC SI
INC.DI.
LOOP AGAIN66
    .ENDIF
\t
;Start addition and subtraction
LEA SI,BUF1
LEADI,BUF2
INC SI
INC SI
INC.DI.
INC.DI.
MOV AL,[SI]
MOVAH,[DI]
\t
.IF AH == AL

DEC BH
MOV CH,0
MOV CL,BH
LEA SI,BUF3
LEADI,BUF4
LEABP,BUF0
AGAIN7: INC SI
INC.DI.
INC.BP
LOOP AGAIN7
DEC SI
DEC DI
DEC BP
\t    
MOVAX,0
MOVBL,0
MOV CH,0
MOV CL,BH
AGAIN8: MOV AL,[SI]
MOVAH,[DI]
ADD AL,AH
.IF BL>0
ADD AL,BL
MOVBL,0
.ENDIF
.IF AL > 9
MOVBL,1
SUB AL,10
.ENDIF
MOV[BP],AL
DEC BP
DEC SI
DEC DI
LOOP AGAIN8
\t\t
MOV CL,BH
ADD CL,1
LEA SI,BUF0
AGAIN9: MOV AL,[SI]
.IF AL != '$'
ADD AL,30H
MOV [SI],AL
.ELSE
MOV AH,'$'
MOV[SI],AH
.ENDIF
INC SI
LOOP AGAIN9
\t\t
LEA DX,message0
    MOVAH,09H
    INT 21H
\t\t
LEA SI,BUF1
INC SI
INC SI
MOV AL,[SI]
.IF AL=='-'
LEA DX,message_fu
    MOVAH,09H
    INT 21H
    .ELSE
    LEA DX,message_zheng
    MOVAH,09H
    INT 21H
    .ENDIF
    \t
\t\t
LEADX,BUF0
    MOVAH,09H
    INT 21H

.ELSE

    DEC BH
MOV CH,0
MOV CL,BH
LEA SI,BUF3
LEADI,BUF4
LEABP,BUF0
AGAIN71: INC SI
INC.DI.
INC.BP
LOOP AGAIN71
DEC SI
DEC DI
DEC BP
\t    
MOVAX,0
MOVBL,0
MOV CH,0
MOV CL,BH
AGAIN81: MOV AL,[SI]
MOVAH,[DI]
.IF AL>AH
SUB AL,AH
SUB AL,BL
.ELSEIF AL==AH
SUB AL,AH
.ELSE
ADD AL,10
SUB AL,AH
MOVBL,1
.ENDIF
\t\t
MOV[BP],AL
DEC BP
DEC SI
DEC DI
LOOP AGAIN81
\t\t
MOV CL,BH
ADD CL,1
LEA SI,BUF0
AGAIN91: MOV AL,[SI]
.IF AL != '$'
ADD AL,30H
MOV [SI],AL
.ELSE
MOV AH,'$'
MOV[SI],AH
.ENDIF
INC SI
LOOP AGAIN91
\t\t
LEA DX,message0
    MOVAH,09H
    INT 21H
\t\t
LEA SI,BUF1
INC SI
INC SI
MOV AL,[SI]
.IF AL==' + '
LEA DX,message_zheng
    MOVAH,09H
    INT 21H
    .ELSE
    LEA DX,message_fu
    MOVAH,09H
    INT 21H
    .ENDIF
\t\t
\t\t
LEADX,BUF0
    MOVAH,09H
    INT 21H
    .ENDIF
    
    
    MOVAH,4CH
    INT 21H
CODES ENDS
END START

5. Test results

Test case: 11111111111111111111 + 22222222222222222222 (20-digit addition)

Test Results:

Test case: -22222222222222222222-11111111111111111111 (subtraction of 20-digit numbers with the same sign)

Test Results:

Test case: + 22222222222222222222-11111111111111111111 (20-digit subtraction of numbers with different signs)

Test Results:

Test case: +123456789-12345678 (9 digits minus 8 digits)

Test Results:

Test case: + 12345678 + 111 (8 digits plus 3 digits)

Test Results:

Through inspection, the above results are correct.

6. Summary

Since there are too many digits for addition and subtraction and they are not uniform in this question, we first unify the digits by padding zeros, then fetch the numbers bit by bit from the memory to the register for addition and subtraction and record the carry and borrow bits, and finally determine the sign. Through testing the program, it can be seen that the code meets the requirements of the topic relatively completely.