>> Technologie Électronique >  >> Audio personnel >> Radios-réveils

Assembleur 8086 : Calcul intervalle temps entre deux événements

Voici un programme assembleur 8086 corrigé et bien commenté (syntaxe MASM/TASM) qui lit deux heures (HH:MM) depuis l'utilisateur, calcule la différence, et l'affiche. Le code original avait erreurs logiques (ex. utilisation `MUL CX` pour conversion décimale, usage registres incorrect, soustraction défectueuse). Cette version utilise arithmétique BCD pour clarté et exactitude.

.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 

Comment ça marche

  1. Entrée : Lit deux heures comme HH:MM (ex. 14:30, 16:45). Valide chiffres implicitement.
  2. Conversion : Convertit chacune en minutes totales depuis minuit (HH×60 + MM).
  3. Soustraction : Calcule différence (Heure2 − Heure1). Si négative, ajoute 1440 minutes (24h) pour passer au jour suivant.
  4. Sortie : Convertit différence en HH:MM et affiche.

Corrections clés vs code original

  • Utilise arithmétique binaire (pas confusion BCD `MUL CX,10`).
  • Gère correctement séparation heure/minute et retenue.
  • Gère correctement passage minuit.
  • Sous-routines modulaires pour entrée, sortie, conversion.
  • Interruptions DOS standard (AH=01h lecture char, AH=02h affiche char, AH=09h affiche chaîne).

Assembler avec MASM/TASM, linker, exécuter dans DOSBox ou vrai DOS. Pour mode protégé 32/64-bit, utiliser API différente (pas INT 21h).

Radios-réveils