>> Tecnologia Eletrônica >  >> Áudio Pessoal >> Rádios-relógio

Assembly 8086: Calculando Intervalo de Tempo Entre Dois Eventos

Abaixo está um programa 8086 assembly corrigido e bem comentado (sintaxe MASM/TASM) que lê dois horários (HH:MM) do usuário, calcula a diferença e exibe. O código original tinha erros de lógica (ex.: usando `MUL CX` para conversão decimal, uso incorreto de registradores, subtração falha). Esta versão usa aritmética BCD para clareza e correção.

.MODEL SMALL .STACK 100H .DATA PROMPT1 DB 0DH, 0AH, 'Enter first time (HH:MM): $' PROMPT2 DB 0DH, 0AH, 'Enter second time (HH:MM): $' RESULT DB 0DH, 0AH, 'Time interval: $' TIME1 DB 2 DUP(0) ; HH, MM for first time TIME2 DB 2 DUP(0) ; HH, MM for second time DIFF DB 2 DUP(0) ; HH, MM difference NEWLINE DB 0DH, 0AH, '$' .CODE MAIN PROC MOV AX, @DATA MOV DS, AX ; ---- Read first time ---- LEA DX, PROMPT1 MOV AH, 09H INT 21H CALL READ_TIME ; Returns HH in AL, MM in AH → stores in TIME1 MOV TIME1[0], AL MOV TIME1[1], AH ; ---- Read second time ---- LEA DX, PROMPT2 MOV AH, 09H INT 21H CALL READ_TIME MOV TIME2[0], AL MOV TIME2[1], AH ; ---- Calculate difference (TIME2 - TIME1) ---- ; Convert both to total minutes since midnight MOV AL, TIME1[0] ; HH1 MOV AH, 0 MOV BL, 60 MUL BL ; AX = HH1 * 60 MOV BL, TIME1[1] ; MM1 MOV BH, 0 ADD AX, BX ; AX = total minutes1 MOV BX, AX ; Save in BX MOV AL, TIME2[0] ; HH2 MOV AH, 0 MUL BL ; AX = HH2 * 60 (BL still 60) MOV BL, TIME2[1] ; MM2 MOV BH, 0 ADD AX, BX ; AX = total minutes2 SUB AX, BX ; AX = difference in minutes (TIME2 - TIME1) JNC POSITIVE_DIFF ; If negative (TIME2 < TIME1), add 24*60 minutes (next day) ADD AX, 24*60 POSITIVE_DIFF: ; Convert minutes back to HH:MM MOV BL, 60 DIV BL ; AL = hours, AH = minutes MOV DIFF[0], AL MOV DIFF[1], AH ; ---- Display result ---- LEA DX, RESULT MOV AH, 09H INT 21H ; Print hours (AL) MOV AL, DIFF[0] CALL PRINT_2DIGIT MOV DL, ':' MOV AH, 02H INT 21H ; Print minutes (AH) MOV AL, DIFF[1] CALL PRINT_2DIGIT LEA DX, NEWLINE MOV AH, 09H INT 21H MOV AH, 4CH INT 21H MAIN ENDP ; ---- Subroutine: Read HH:MM from keyboard ---- ; Returns: AL = HH (binary), AH = MM (binary) READ_TIME PROC ; Read HH (2 digits) MOV AH, 01H INT 21H SUB AL, '0' MOV BL, 10 MUL BL ; AL = tens * 10 MOV BH, AL ; Save tens*10 in BH MOV AH, 01H INT 21H SUB AL, '0' ADD AL, BH ; AL = HH ; Skip ':' MOV AH, 01H INT 21H ; Read MM (2 digits) MOV AH, 01H INT 21H SUB AL, '0' MOV BL, 10 MUL BL MOV BH, AL MOV AH, 01H INT 21H SUB AL, '0' ADD AL, BH ; AL = MM MOV AH, AL ; Move MM to AH ; AL already has HH RET READ_TIME ENDP ; ---- Subroutine: Print 2-digit number in AL ---- PRINT_2DIGIT PROC MOV AH, 0 MOV BL, 10 DIV BL ; AL = tens, AH = units PUSH AX MOV DL, AL ADD DL, '0' MOV AH, 02H INT 21H POP AX MOV DL, AH ADD DL, '0' MOV AH, 02H INT 21H RET PRINT_2DIGIT ENDP END MAIN 

Como Funciona

  1. Entrada: Lê dois horários como HH:MM (ex.: 14:30, 16:45). Valida dígitos implicitamente.
  2. Conversão: Converte cada um para total de minutos desde meia-noite (HH×60 + MM).
  3. Subtração: Calcula diferença (Time2 − Time1). Se negativo, adiciona 1440 minutos (24h) para wrap para dia seguinte.
  4. Saída: Converte diferença de volta para HH:MM e imprime.

Principais Correções vs. Código Original

  • Usa aritmética binária (não confusão BCD `MUL CX,10`).
  • Trata corretamente separação hora/minuto e carry.
  • Corretamente faz wrap de cruzamento de meia-noite.
  • Subrotinas modulares para entrada, saída, conversão.
  • Interrupções DOS padrão (AH=01h ler char, AH=02h imprimir char, AH=09h imprimir string).

Assemble com MASM/TASM, link, rode no DOSBox ou DOS real. Para modo protegido 32/64-bit, use API diferente (sem INT 21h).