Advertisement
aaron-kristopher

sum_product

Mar 17th, 2024 (edited)
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ASM (NASM) 15.16 KB | Source Code | 0 0
  1. .MODEL SMALL
  2. .STACK 100h
  3.  
  4. .DATA                               ; Data segment for variables and messages
  5.     ; Variables
  6.     input_integer DB '$$$$$$$$$$'   ; Buffer to store input string
  7.     num_one DW ?                    ; First number
  8.     num_two DW ?                    ; Second number
  9.     sum DW ?                        ; Sum of the numbers
  10.     product DW ?                    ; Product of the numbers
  11.     string_sum DW '$$'              ; String to hold formatted sum
  12.     string_product DW '$$'          ; String to hold formatted product
  13.     len DB 0
  14.  
  15.     ; Messages
  16.     input_prompt DB 13, 10, 'Enter a number (0 - 99): $'
  17.     invalid_input_prompt DB 13, 10, 13, 10, 'Invalid input!!!', 13, 10, '$'
  18.     integer_out_of_range_prompt DB 13, 10, 13, 10, 'Input out of range! Must be (0 - 9).', 13, 10, '$'
  19.     echo_sum DB 13, 10, 'The Sum: $'
  20.     echo_product DB 13, 10, 'The Product: $'
  21.  
  22.  
  23. .CODE                           ; Denotes the start of the code segment
  24. MAIN PROC                       ; Defines the main procedure (program entry point)
  25.  
  26.   ; Set up data segment
  27.   MOV AX, @data                 ; Move address of data segment to AX register
  28.   MOV DS, AX                    ; Set the data segment register (DS) to the address in AX
  29.  
  30.   ; Get the first number
  31. get_num_one:
  32.   CALL SCANF_INTEGER            ; Call procedure to prompt user and read integer input
  33.   CMP CX, 3                     ; Checks if the length of the input is greater than 3, if so it means it is 100 or greater
  34.   JL set_num_one                ; Process continues if it is below length of 2
  35.  
  36.   ; Is called if input is greater than 99
  37.   CALL INTEGER_OUT_OF_RANGE
  38.   JMP get_num_one
  39.  
  40. set_num_one:
  41.   PUSH OFFSET input_integer ; Push address of input buffer onto stack (for PARSE_INTEGER)
  42.   CALL PARSE_INTEGER  ; Call procedure to convert string input to integer
  43.   MOV num_one, BX      ; Move parsed integer from BX to num_one variable
  44.  
  45.   ; Get the second number (similar steps as above)
  46. get_num_two:
  47.   CALL SCANF_INTEGER
  48.   CMP CX, 3
  49.   JL set_num_two
  50.  
  51.   CALL INTEGER_OUT_OF_RANGE
  52.   JMP get_num_two
  53.  
  54. set_num_two:
  55.   PUSH OFFSET input_integer
  56.   CALL PARSE_INTEGER
  57.   MOV num_two, BX
  58.  
  59.   ; Perform addition and display sum
  60.   CALL ADDITION                 ; Call procedure to add num_one and num_two
  61.   CALL PARSE_SUM                ; Call procedure to convert sum to string representation
  62.   CALL DISPLAY_SUM              ; Call procedure to display the sum on the console
  63.  
  64.   ; Perform multiplication and display product
  65.   CALL MULTIPLICATION           ; Call procedure to multiply num_one and num_two
  66.   CALL PARSE_PRODUCT            ; Call procedure to convert product to string representation
  67.   CALL DISPLAY_PRODUCT          ; Call procedure to display the product on the console
  68.  
  69.   ; Terminate the program
  70.   MOV AH, 4Ch                   ; Set interrupt code for program termination (4Ch)
  71.   INT 21h                       ; Trigger interrupt to end program
  72.  
  73. MAIN ENDP                       ; End of the main procedureSCANF_INTEGER PROC
  74.  
  75. SCANF_INTEGER PROC
  76.   ; Preserve registers to avoid side effects
  77.   PUSH AX                       ; Save AX on the stack
  78.   PUSH BX                       ; Save BX on the stack
  79.   PUSH SI                       ; Save SI on the stack
  80.  
  81. next_integer:
  82.   ; Initialize variables for input reading
  83.   XOR SI, SI                    ; Set SI (character counter) to zero
  84.   LEA BX, input_integer         ; Load address of input_integer buffer into BX
  85.  
  86.   ; Print prompt for user input
  87.   LEA DX, input_prompt          ; Load address of prompt message
  88.   MOV AH, 09h                   ; DOS function to display string
  89.   INT 21h                       ; Call DOS interrupt to display prompt
  90.  
  91. read_next_char:
  92.   ; Read a character from standard input
  93.   MOV AH, 01h                   ; DOS function to read character
  94.   INT 21h                       ; Call DOS interrupt to read input
  95.  
  96.   ; Validate the input character
  97. validate_input:
  98.   CMP AL, 13                    ; Check if Enter key was pressed (13 = carriage return)
  99.   JE done_reading               ; If Enter pressed, jump to done_reading
  100.  
  101.   ; Check if character is a valid digit (0-9)
  102.   CMP AL, '0'                   ; Compare with '0'
  103.   JL invalid_input              ; If less than '0', jump to invalid_input
  104.   CMP AL, '9'                   ; Compare with '9'
  105.   JG invalid_input              ; If greater than '9', jump to invalid_input
  106.  
  107.   ; Store valid character in the input_integer buffer
  108.   MOV [BX+SI], AL               ; Store character at BX+SI offset
  109.  
  110.   INC SI                        ; Increment counter
  111.   JMP read_next_char            ; Continue reading next character
  112.  
  113. invalid_input:
  114.   ; Print invalid input message
  115.   LEA DX, invalid_input_prompt  ; Load address of invalid input message
  116.   MOV AH, 09h                   ; DOS function to display string
  117.   INT 21h                       ; Call DOS interrupt to display message
  118.  
  119.   JMP next_integer              ; Restart input process
  120.  
  121. done_reading:
  122.   ; Terminate the string with a null terminator
  123.   MOV AL, '$'                   ; Load dollar sign (string terminator)
  124.   MOV [BX+SI], AL               ; Store terminator at the end of input
  125.  
  126.   MOV CX, SI                    ; Save the character count in CX
  127.  
  128.   ; Restore original register values
  129.   POP SI                        ; Restore SI from the stack
  130.   POP BX                        ; Restore BX from the stack
  131.   POP AX                        ; Restore AX from the stack
  132.  
  133.   RET                           ; Return from the procedure
  134.  
  135. SCANF_INTEGER ENDP
  136.  
  137. PARSE_INTEGER PROC
  138.   ; Set up variables
  139.   MOV SI, OFFSET input_integer  ; Load address of input string into SI
  140.   MOV BX, 0                     ; Initialize BX to hold the parsed integer (0)
  141.  
  142. iterate:
  143.   ; Check for end of string
  144.   XOR AX, AX
  145.   MOV AX, [SI]                  ; Load character from input string at SI
  146.   CMP AL, '$'                   ; Compare with dollar sign terminator
  147.   JE exit                       ; Jump to exit if it's the terminator
  148.  
  149.   ; Convert ASCII digit to numeric value (0-9)
  150.   SUB AX, 48                    ; Subtract '0' from ASCII code to get digit value
  151.   CMP CX, 1                     ; Check if this is the first digit
  152.   JE add                        ; If first digit, jump to add (no multiplication)
  153.   MOV DX, 10                    ; Otherwise, set multiplier to 10
  154.  
  155.   MUL DX                        ; Multiply current value by 10 (for multiple digits)
  156.  
  157. add:
  158.   ; Add the digit value to the parsed integer
  159.   ADD BX, AX                    ; Add current digit value to BX
  160.  
  161.   ; Update loop variables
  162.   INC SI                        ; Increment SI to point to next character
  163.   DEC CX                        ; Decrement counter for number of digits
  164.  
  165.   ; Continue iterating until all characters are processed
  166.   CMP CX, 0                     ; Check if counter reaches zero
  167.   JNE iterate                   ; Jump back to iterate if not done
  168.  
  169. exit:
  170.   ; Procedure finished
  171.   RET                           ; Return from the procedure
  172.  
  173. PARSE_INTEGER ENDP
  174.  
  175. ADDITION PROC
  176.  
  177.   ; Get operands from variables
  178.   MOV AX, num_one               ; Load the value of num_one into AX
  179.  
  180.   ; Add the operands
  181.   MOV BX, num_two               ; Load the value of num_two into BX
  182.   ADD AX, BX                    ; Add the values in AX and BX, storing the result in AX
  183.  
  184.   ; Store the result in the sum variable
  185.   MOV sum, AX                   ; Move the sum from AX to the sum variable
  186.  
  187.   ; Return from the procedure
  188.   RET                           ; Return control to the calling procedure
  189.  
  190. ADDITION ENDP
  191.  
  192. MULTIPLICATION PROC
  193.  
  194.   ; Get operands from variables
  195.   MOV AX, num_one               ; Load the value of num_one into AX
  196.   XOR AH, AH                    ; Clear the upper byte of AX (important for unsigned multiplication)
  197.  
  198.   ; Get operand from variable and clear upper byte
  199.   MOV BX, num_two               ; Load the value of num_two into BX
  200.   XOR BH, BH                    ; Clear the upper byte of BX (important for unsigned multiplication)
  201.  
  202.   ; Perform unsigned multiplication
  203.   MUL BX                        ; Multiply the values in AX and BX, storing the result in AX and DX
  204.  
  205.   ; Store the result (lower 16 bits) in the product variable
  206.   MOV product, AX               ; Move the lower 16 bits of the product (in AX) to the product variable
  207.  
  208.   ; Return from the procedure
  209.   RET                           ; Return control to the calling procedure
  210.  
  211. MULTIPLICATION ENDP
  212.  
  213. PARSE_SUM PROC
  214.   ; Set up variables
  215.   MOV AX, sum                   ; Load the value of the sum from the sum variable into AX
  216.   XOR AH, AH                    ; Clear the upper byte of AX (important for converting to ASCII)
  217.   XOR CX, CX                    ; Initialize CX to zero (used as a counter)
  218.  
  219. add_next_div:
  220.   ; Prepare for division (remainder in DX, quotient in AX)
  221.   XOR DX, DX                    ; Clear the DX register (important for division)
  222.  
  223.   MOV BX, 10                    ; Set divisor to 10 (for extracting digits)
  224.   DIV BX                        ; Perform unsigned division of AX by 10
  225.                                 ;  - Quotient (result of division) is stored in AX
  226.                                 ;  - Remainder is stored in DX
  227.  
  228.   ; Convert remainder digit to ASCII
  229.   ADD DX, '0'                   ; Add '0' to the remainder (DX) to get the corresponding ASCII digit character
  230.  
  231.   ; Store the digit character and update loop variables
  232.   PUSH DX                       ; Push the digit character onto the stack (for string building)
  233.   INC CX                        ; Increment the counter (CX) for the number of digits
  234.   CMP AX, 0                     ; Check if the quotient (AX) is zero (indicating all digits processed)
  235.   JE add_pop_queue              ; If zero, jump to add_pop_queue (to build the string)
  236.   JMP add_next_div              ; Otherwise, continue dividing by 10 (extract next digit)
  237.  
  238. add_pop_queue:
  239.   ; Set up for building the string in string_sum
  240.   LEA BX, string_sum            ; Load the address of string_sum into BX (destination for the string)
  241.   XOR SI, SI                    ; Initialize SI as a string counter (offset within string_sum)
  242.  
  243. add_pop_next:
  244.   ; Pop digit characters from the stack and build the string
  245.   POP DX                        ; Pop a digit character from the stack
  246.   MOV [BX+SI], DL               ; Move the digit character (lower byte of DX) to the string_sum at current offset
  247.   INC SI                        ; Increment the string counter (SI)
  248.   LOOP add_pop_next             ; Loop back to pop_next until all digits are processed from the stack
  249.  
  250.   ; Add string terminator ('$')
  251.   MOV DL, '$'                   ; Load the dollar sign character into DL
  252.   MOV [BX+SI], DL               ; Move the terminator character to the end of the string_sum
  253.  
  254.   ; Return the address of the converted string
  255.   MOV DX, BX                    ; Move the base address of string_sum into DX to return
  256.  
  257.   RET                           ; Return from the procedure
  258.  
  259. PARSE_SUM ENDP
  260.  
  261. PARSE_PRODUCT PROC
  262.   ; Set up variables
  263.   MOV AX, product               ; Load the value of the product from the product variable into AX
  264.   XOR CX, CX                    ; Initialize CX to zero (used as a counter)
  265.  
  266. mult_next_div:
  267.   ; Prepare for division (remainder in DX, quotient in AX)
  268.   XOR DX, DX                    ; Clear the DX register (important for division)
  269.  
  270.   MOV BX, 10                    ; Set divisor to 10 (for extracting digits)
  271.   DIV BX                        ; Perform unsigned division of AX by 10
  272.                                 ;  - Quotient (result of division) is stored in AX
  273.                                 ;  - Remainder is stored in DX
  274.  
  275.   ; Convert remainder digit to ASCII
  276.   ADD DX, '0'                   ; Add '0' to the remainder (DX) to get the corresponding ASCII digit character
  277.  
  278.   ; Store the digit character and update loop variables
  279.   PUSH DX                       ; Push the digit character onto the stack (for string building)
  280.   INC CX                        ; Increment the counter (CX) for the number of digits
  281.   CMP AX, 0                     ; Check if the quotient (AX) is zero (indicating all digits processed)
  282.   JE mult_pop_queue             ; If zero, jump to mult_pop_queue (to build the string)
  283.   JMP mult_next_div             ; Otherwise, continue dividing by 10 (extract next digit)
  284.  
  285. mult_pop_queue:
  286.   ; Set up for building the string in string_product
  287.   LEA BX, string_product            ; Load the address of string_product into BX (destination for the string)
  288.   XOR SI, SI                    ; Initialize SI as a string counter (offset within string_product)
  289.  
  290. mult_pop_next:
  291.   ; Pop digit characters from the stack and build the string
  292.   POP DX                        ; Pop a digit character from the stack
  293.   MOV [BX+SI], DL               ; Move the digit character (lower byte of DX) to the string_product at current offset
  294.   INC SI                        ; Increment the string counter (SI)
  295.   LOOP mult_pop_next            ; Loop back to pop_next until all digits are processed from the stack
  296.  
  297.   ; Add string terminator ('$')
  298.   MOV DL, '$'                   ; Load the dollar sign character into DL
  299.   MOV [BX+SI], DL               ; Move the terminator character to the end of the string_product
  300.  
  301.   ; Return the address of the converted string
  302.   MOV DX, BX                    ; Move the base address of string_product into DX to return
  303.  
  304.   RET                           ; Return from the procedure
  305.  
  306. PARSE_PRODUCT ENDP
  307.  
  308. DISPLAY_SUM PROC
  309.  
  310.   ; Display message "The sum is: "
  311.   LEA DX, echo_sum              ; Load the address of the message string "The sum is: " into DX
  312.   MOV AH, 09h                   ; Set interrupt code for displaying a string (DOS function)
  313.   INT 21h                       ; Trigger interrupt to display the message
  314.  
  315.   ; Display the actual sum value
  316.   LEA DX, string_sum            ; Load the address of the converted sum string (from PARSE_SUM) into DX
  317.   MOV AH, 09h                   ; Set interrupt code for displaying a string (DOS function)
  318.   INT 21h                       ; Trigger interrupt to display the sum value
  319.  
  320.   RET                           ; Return from the procedure
  321.  
  322. DISPLAY_SUM ENDP
  323.  
  324. DISPLAY_PRODUCT PROC
  325.  
  326.   ; Display message "The product is: "
  327.   LEA DX, echo_product          ; Load the address of the message string "The product is: " into DX
  328.   MOV AH, 09h                   ; Set interrupt code for displaying a string (DOS function)
  329.   INT 21h                       ; Trigger interrupt to display the message
  330.  
  331.   ; Display the actual product value
  332.   LEA DX, string_product        ; Load the address of the converted product string (from PARSE_PRODUCT) into DX
  333.   MOV AH, 09h                   ; Set interrupt code for displaying a string (DOS function)
  334.   INT 21h                       ; Trigger interrupt to display the product value
  335.  
  336.   RET                           ; Return from the procedure
  337.  
  338. DISPLAY_PRODUCT ENDP
  339.  
  340. INTEGER_OUT_OF_RANGE PROC
  341.  
  342.   ; Display message "Input out of range. Must be (0 - 9)."
  343.   LEA DX, integer_out_of_range_prompt
  344.   MOV AH, 09h                   ; Set interrupt code for displaying a string (DOS function)
  345.   INT 21h                       ; Trigger interrupt to display the product value
  346.  
  347.   RET                           ; Return from the procedure
  348.  
  349. INTEGER_OUT_OF_RANGE ENDP
  350.  
  351. END
  352.  
Tags: assembly
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement