;============================================================================= ; 3n.asm ; The 3n+1 problem solution... ;(C)I don't take any responsibility for the use of this program ; Zedr0n -- connection closed ;============================================================================= ;============================================================================= ; .Com declaration ;============================================================================= .MODEL TINY LOCALS @@ ;============================================================================= ; Data definition/declaration ;============================================================================= .DATA ;----------------------------------------------------------------------------- ; Equals ;----------------------------------------------------------------------------- INCLUDE ..\LIB\DEFS.INC ;----------------------------------------------------------------------------- ; Constants ;----------------------------------------------------------------------------- PATH DB "A.IN",0 ;----------------------------------------------------------------------------- ; File variables ;----------------------------------------------------------------------------- HFILE DW ? ; I DW ? J DW ? ; N DW ? CUR_CHAR DB ? ; INT_TXT DB 6 DUP(?) MAX DW ? NUMBUFF DB 34 DUP(?) ;----------------------------------------------------------------------------- ; Stack variables ;----------------------------------------------------------------------------- .CODE .386 ORG 100H ;============================================================================= ; Code segment ;============================================================================= START: ; ; << Open file >> CALL OPEN_FILE ; Open file a.in ; << Calculate for one_pair >> CONT: CALL GET_INPUT ; Get pair of integers CALL GET_ONE_PAIR ; Calculate maximum for one pair of integers CALL GET_NEW_LINE ; Warp to new line OR AX,AX ; Is there a new line? JNZ CONT ; If yes, continue calculating ; << Close file >> CALL CLOSE_FILE ; Close file RET ;============================================================================= ; Procedures ;============================================================================= ;----------------------------------------------------------------------------- ; Get_Input - get a pair of integers ;----------------------------------------------------------------------------- GET_INPUT PROC ; ; << Get pair of integers >> CALL READ_INTEGER MOV I,AX ; Save I CALL READ_INTEGER ; MOV J,AX ; Save J RET GET_INPUT ENDP ;----------------------------------------------------------------------------- ; Open_File - open the file, what can it do else? ;----------------------------------------------------------------------------- OPEN_FILE PROC ; XOR AX,AX ; Read-only mode MOV AH,3DH ; Open file function XOR CX,CX ; No server MOV DX,OFFSET PATH ; Filename INT 21H ; Call interrupt MOV HFILE,AX ; Save handle RET OPEN_FILE ENDP ;----------------------------------------------------------------------------- ; Close_file - close the file ;----------------------------------------------------------------------------- CLOSE_FILE PROC MOV AH,3EH ; Close file function MOV BX,HFILE ; Restore handle INT 21H ; Call interrupt RET CLOSE_FILE ENDP ;----------------------------------------------------------------------------- ; Read_integer - read the integer from file ; Output: AX - read integer ;----------------------------------------------------------------------------- READ_INTEGER PROC ; MOV DI,OFFSET INT_TXT ; MOV CX,6 ; Length is 5 digits CALL CLEAR_BUFFER ; Clear the buffer XOR BX,BX ; Current index in buffer = 0 @@R1: PUSH BX ; Save BX, because Read_char changes it CALL READ_CHAR ; Read one character from file POP BX ; Restore BX CMP AH,20H ; Is it space? JZ @@R2 ; CMP AH,0DH ; Is it end of line? JZ @@R2 ; CMP AH,0AH ; -||- JZ @@R2 ; MOV INT_TXT[BX],AH ; Save into buffer INC BX ; New index in buffer JMP @@R1 ; Continue loop @@R2: ; MOV SI,OFFSET INT_TXT ; CALL CONVERT_TO_INTEGER ; Convert the read from file text to integer RET READ_INTEGER ENDP ;----------------------------------------------------------------------------- ; Read_char - read one character from file ; AH - character, which has been read ;----------------------------------------------------------------------------- READ_CHAR PROC ; MOV AH,3FH ; Read from file function MOV BX,HFILE ; Restore file handle MOV CX,1 ; Read one character MOV DX,OFFSET CUR_CHAR ; Read into following buffer INT 21H ; Call interrupt MOV AH,CUR_CHAR RET READ_CHAR ENDP ;----------------------------------------------------------------------------- ; Convert_to_integer - convert text to integer ; Input: ; SI - buffer offset ; Output: ; AX - integer ;----------------------------------------------------------------------------- CONVERT_TO_INTEGER PROC ; XOR CX,CX ; Clear the cycle-length @@C1: LODSB ; Read byte SUB AL,30H ; Convert to digit MOVZX BX,AL ; Extend to word in BX ADD CX,BX ; Add to integer IMUL CX,10 ; Now multiply by 10 CMP [SI+1],0 ; If it will be the last, then we shouldn't ; multiply by 10 JNZ @@C1 ; MOVZX AX,BYTE PTR [SI] ; Now get the last character SUB AX,30H ; Convert to digit ADD AX,CX ; Now add the last digit RET CONVERT_TO_INTEGER ENDP ;----------------------------------------------------------------------------- ; Clear_buffer - fill the buffer with 0's ; Input: ; DI - buffer offset ; CX - buffer length ;----------------------------------------------------------------------------- CLEAR_BUFFER PROC ; XOR AL,AL ; Put 0 @@C1: STOSB ; Put byte DEC CX ; Is it end? JNZ @@C1 ; Then loop RET CLEAR_BUFFER ENDP ;----------------------------------------------------------------------------- ; Get_cycle - get the number of cycles ; Input: ; AX - N ; Output: ; AX - number of cycles ;----------------------------------------------------------------------------- GET_CYCLE PROC ; MOV CX,1 ; We have at least one cycle CMP AX,1 ; If AX=1 then we should end it, because ; otherwise we get infinite loop JZ @@EXIT @@G0: PUSH AX AND AX,1 ; Isn't it odd? JZ @@G2 ; If not, then divide by 2 @@G1: ; POP AX IMUL AX,3 ; N=3*N+1 INC AX ; JMP @@G3 @@G2: ; POP AX SHR AX,1 ; N=N/2 @@G3: ; INC CX ; Increase cycle-length CMP AX,1 ; N=1? JNZ @@G0 ; If not => continue loop @@EXIT: MOV AX,CX ; RET GET_CYCLE ENDP ; ;----------------------------------------------------------------------------- ; Get_one_pair - calculate for one pair... ;----------------------------------------------------------------------------- GET_ONE_PAIR PROC MOV AX,I ; N=I at first MOV N,AX MOV MAX,0 ; Maximum is 0 at first,too I_TO_J: MOV AX,N CALL GET_CYCLE ; Get cycle-length for current N CMP MAX,AX ; If new is more than previous maximum JG MORE ; MOV MAX,AX ; Then set new maximum MORE: ; INC N ; Increase N MOV AX,N ; CMP AX,J ; Is N>J? JLE I_TO_J ; If not => continue loop ; << Show I and space >> MOV AX,I ; CALL HEXDEC ; CALL OUTPUT ; Show I MOV AH,02H ; Show character function MOV DL,20H ; INT 21H ; Show space ; << Show J and space >> MOV AX,J ; CALL HEXDEC ; CALL OUTPUT ; Show J MOV AH,02H ; Show character function MOV DL,20H ; INT 21H ; Space ; << Show maximum and warp to new line >> MOV AX,MAX ; CALL HEXDEC ; CALL OUTPUT ; MOV AH,02H ; MOV DL,0DH ; INT 21H ; MOV DL,0AH ; INT 21H RET GET_ONE_PAIR ENDP ;----------------------------------------------------------------------------- ; Get_new_line - warp to new line in file, if present ;----------------------------------------------------------------------------- GET_NEW_LINE PROC ; @@G1: CALL READ_CHAR ; Try to read character OR AL,AL ; Is it EOF? JZ @@FAULT ; If yes => @@FAULT CMP AH,0AH ; Is it end of line? JZ @@G1 ; If yes, continue reading... @@G2: MOV AH,42H ; Lseek function MOV AL,1 ; Current file position MOV BX,HFILE ; Restore handle MOV CX,-1 MOV DX,-1 ; Offset = -1 INT 21H ; Call interrupt MOV AX,1 ; Mission successful RET ; @@FAULT: ; XOR AX,AX ; EOF RET GET_NEW_LINE ENDP INCLUDE ..\LIB\HEXDECL.INC ; END START ;