;---------------------------------------------------------------------------- ; CS272 - ADC_a.Asm Add With Carry ; ; - Input two Hex numbers from the Keyboard (Make sure each Nibble is Hex) ; - Add them together ; - Output the Sum to the Screen ; ;---------------------------------------------------------------------------- Data Segment ;----------------------Go for it...Make Max_Nibbles Larger!------------------ ; Max_Nibbles = 254D ;Maximum Number of nibbles allowed ; ^ ; \_____Note: Max_Nibbles must be divisible by 2 for the program ; to work properly. ; ; [ Program has been validated for values of 'Max_Nibbles' from 2 --> 254 ] ; ; [ It does NOT work for values of 256 or greater....care to speculate why? ] ; ;---------------------------------------------------------------------------- Welcome_Message DB 'This program does Addition of two Hex strings', 0DH, 0AH DB 0AH DB 'Enter Hex digit String ', 0DH, 0AH DB 0AH, '$' Mess2 DB 0DH, 0AH, 0DH, 0AH DB 'Enter 2nd Hex String ', 0DH, 0AH DB 0AH, '$' Dashes DB Max_Nibbles + 1 DUP("-"), 0DH, 0AH, '$' Bad_Hex DB 07D, "<--Not HEX....try character again", 07D, "$" Clr_Msg DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 DB " " DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, "$" New_Line DB 0DH, 0AH, '$' In_Buff DB Max_Nibbles DUP("*") ;Input from keyboard is stored here! ; The Number_1 & 2 areas are nn bytes long for input of up to nn ASCII/Hex ; nibbles each. The ASCII/Hex bytes are then packed 2 to a byte and ; stored in the right nn/2 bytes (nn nibbles) of Number_1 & 2. The sum ; on Number_1 & 2 is stored in the right nn/2 bytes of Number_2. Number_1 DB Max_Nibbles DUP(00H) ;1st Hex Number Number_2 DB Max_Nibbles DUP(00H) ;2nd Hex Number (& Sum) My_Carry DB 'N' ;Copy carry flag here! ; Y = Carry ; N = No Carry Data EndS Working_Storage Segment Stack DW 100H DUP(?) Working_Storage EndS Code Segment Assume CS:Code,DS:Data,SS:Working_Storage Prog_Start: Mov AX,Data ; Init Mov DS,AX ; DS Mov ES,AX ; and ES Mov DX,OffSet Welcome_Message ; Welcome user...ask for Mov AH,9H ; first Hex string Int 21H ; ; Get first Hex String Call Get_Hex_S ; Get & check 1st hex string ; Move Hex String to Number_1 (right-justified) ; (still in the 1 nibble per byte format!) Mov SI, Offset In_Buff ; Point to Source Add SI, CX ; Go to right end Sub SI, 1 ; of source string Mov DI, Offset Number_1 ; and Number_1 is where we want Add DI, Max_Nibbles - 1 ; the Right-Justified Number ; String length is already in CX Std ; Set move direction to Left Rep MovSB ; Move the string to Number_1 Mov BX, Offset Number_1 ; Point to left most byte Mov CH, Max_Nibbles/2 ; Init counter A_Loop: Mov AH, [BX] ; Byte to AH Inc BX ; Point to next byte Mov DL, [BX] ; Next byte to DL Inc BX ; Point to next byte Mov CL, 4 ; ShL DX, CL ; shift it Left 4 bits Mov AL, DL ; Are you following this? ShL AX, CL ; Now two Hex Nibbles are in AH Push AX ; Put it on the stack Sub CH, 1 ; JA A_Loop ; go pack another 2 nibbles Mov BX, Offset Number_1 ; Point to left-most byte Add BX, Max_Nibbles - 1 ; Point to right-most byte Mov CX, Max_Nibbles/2 ; Init counter B_Loop: Pop AX ; Get the last word off Stack Mov [BX], AH ; Move the 2 nibbles to [BX] Dec BX ; Point to next byte to left Dec CX ; Loop counter JA B_Loop ; Get another 2 nibbles ; Get Second Hex String Mov DX, OffSet Mess2 ; Ask for 2nd string of Hex Mov AH, 9H Int 21H Call Get_Hex_S ; Get & check 1st hex string ; Move Hex String to Number_2 (right-justified) ; (still in the 1 nibble per byte format!) Mov SI, Offset In_Buff ; Point to Source Add SI, CX ; Go to right end Sub SI, 1 ; of source string Mov DI, Offset Number_2 ; and Number_1 is where we want Add DI, Max_Nibbles - 1 ; the Right-Justified Number ; String length is already in CX Std ; Set move direction to Left Rep MovSB ; Move the string to Number_1 Mov BX, Offset Number_2 ; Point to left most byte Mov CH, Max_Nibbles/2 ; Init counter C_Loop: Mov AH, [BX] ; Byte to AH Inc BX ; Point to next byte Mov DL, [BX] ; Next byte to DL Inc BX ; Point to next byte Mov CL, 4 ; ShL DX, CL ; shift it Left 4 bits Mov AL, DL ; Are you following this? ShL AX, CL ; Now two Hex Nibbles are in AH Push AX ; Put it on the stack Sub CH, 1 ; JA C_Loop ; go pack another 2 nibbles Mov BX, Offset Number_2 ; Point to left-most byte Add BX, Max_Nibbles - 1 ; Point to right-most byte Mov CX, Max_Nibbles/2 ; Init counter D_Loop: Pop AX ; Get the last word off Stack Mov [BX], AH ; Move the 2 nibbles to [BX] Dec BX ; Point to next byte to left Dec CX ; Loop counter JA D_Loop ; Get another 2 nibbles Mov DL, " " ; Print leading Mov AH, 2 ; Space for Int 21H ; first number being added Mov BX, Offset Number_1 ; Setup BX to print Number_1 Call Print_Hex ; Print Number_1 on screen Mov DL, "+" ; Print leading Mov AH, 2 ; '+' for Int 21H ; second number being added Mov BX, Offset Number_2 ; Setup BX to print Number_2 Call Print_Hex ; Print Number_1 on screen Call Add_nn_Nibbles ; Add Number_1 to Number_2 ; (Sum to Number_2) Mov DX, OffSet Dashes ; We need a line to Sum 'em... Mov AH, 9H Int 21H Cmp My_Carry, "Y" ; Check for carry on last ADC JE Type_1 ; Yes.. Mov DL, " " ; No... Jmp Nxt_1 ; Type_1: Mov DL, "1" ; Nxt_1: Mov AH, 2 ; Type single Character from DOS Int 21H ; Mov BX, Offset Number_2 ; Setup BX to print Number_2 Call Print_Hex ; Print the Sum on screen Done: Mov AX,4C00H ; Return to DOS Int 21H ; ;--------------------------------------------------------------------------- ; - Get characters from keyboard one at a time (end after nn char.entered) ; - Validate each character as HEX (0-9, A-F) ; - Place in In_Buff string ; Get_Hex_S: Mov BX, Offset In_Buff ; Make [BX] point to In_Buff Mov CX, 0 ; Clear Char.Counter Next_Byte: Mov AH, 1H ; Get Character Int 21H ; from keyboard Here_Corr: Cmp AL, 0DH ; Is it a JE GHN_Done ; YES - End of String ; Make sure Character is Hex.... Cmp AL, 48D ; Compare it to "0" JB Not_Hex ; Less than "0" is Invalid Cmp AL, 57D ; Compare it to "9" JLE Good_Hex ; Less or Equal to "9" is Hex Cmp AL, "A" ; Compare it to "A" JL Not_Hex ; Less than "A" is Invalid Cmp AL, "F" ; Compare it to "F" JG Not_Hex ; Greater than "F" is Invalid Sub AL, 7D ; Since it is A->F Sub 7 ; so it will be just above "9" Good_Hex: Sub AL, 48D ; Now convert the byte to a ; Hex nibble (0000 -> 1111) Mov [BX], AL ; Store the full byte as part ; of string...however we will ; only use right 4 bits (nibble) Add BX, 1 ; Point to next byte Add CX, 1 ; Increment Byte counter Cmp CX, Max_Nibbles ; Check if we have max.nibbles JE GHN_Done ; YES - Max.Char.in string... Jmp Next_Byte ; Go get next Char.from Terminal Not_Hex: Mov DX, OffSet Bad_Hex ; Place Hex error message Mov AH, 9H ; on screen Int 21H ; Mov AH, 8H ; Get Character from keyboard Int 21H ; but don't put on screen Push AX ; Save the character Mov DX, OffSet Clr_Msg ; Clear error message Mov AH, 9H ; on screen Int 21H ; Pop AX ; Restore the character Mov DL, AL ; Put the char.entered in DL Mov AH, 2H ; Now put the Character they Int 21H ; entered on the screen Jmp Here_Corr ; Go let the user try again... GHN_Done: Mov DX, OffSet New_Line ; Print a new line Mov AH, 9H ; on screen Int 21H Mov DX, OffSet New_Line ; Print a new line Mov AH, 9H ; on screen Int 21H Ret ;--------------------------------------------------------------------------- ; ; Add_nn_Nibbles: Mov DL, 0 ; Init Byte counter Mov BX, Offset Number_1 ; Left end of Number_1 Add BX, Max_Nibbles - 1 ; Right end byte of Number_1 A32N: Mov AL, [BX] ; Byte to AL Add BX, Max_Nibbles ; Point to Number_2 String Mov AH, [BX] ; Byte to AH Cmp My_Carry, "N" ; Test my carry JE No_Carry ; STC ; Set Carry Flag Jmp AN1 ; No_Carry: CLC ; Clear Carry Flag AN1: ADC AH, AL ; ADC AL --> AH JNC NC ; Jump on No Carry Flag Set Mov My_Carry, "Y" ; Set My_Carry to "Y" Jmp Carry_OK ; NC: Mov My_Carry, "N" ; Set My_Carry to "N" Carry_OK: Mov [BX], AH ; Place Sum in Number_2 String Sub BX, Max_Nibbles + 1 ; Point to previous byte in ; Number_1.... Add DL, 1 ; Count another byte Cmp DL, Max_Nibbles/2 ; Are we done? JL A32N ; No....loop Ret ; Yes...return.... ;--------------------------------------------------------------------------- ; ; Print_Hex: Add BX, Max_Nibbles/2 ; jump to first answer nibble Mov CH, 0 ; Init byte counter PHS2_Loop: Cmp CH, Max_Nibbles/2 ; Check for all done JGE PHS2_Exit ; Yes...get out of here! Mov AX, [BX] ; Get a byte Add BX,1 ; Have BX point to next Byte Add CH,1 ; Count them bytes Call PHS2 ; Keep those Calls balanced! Jmp PHS2_Loop PHS2: Push AX ; Save the byte Mov CL,4 ; Get ready to rotate 4 bits ROR AL,CL ; do it! Call Print_One_Hex_Digit Pop AX Print_One_Hex_Digit: And AL,0FH ;This Add AL,30H ; makes Binary Cmp AL,3AH ; into Hex JB Display_It ; ASCII Add AL,7H ; (Jumps between 9 -> A) Display_It: Mov DL,AL ;Print the Mov AH,2H ; Hex nibble that has been Int 21H ; converted to ASCII Ret PHS2_Exit: Mov DX, OffSet New_Line ; Print a new line Mov AH, 9H ; on screen Int 21H Ret ;---------------------------------------------------------------------------- Code EndS End Prog_Start