assemblysumx86-16number-formattingemu8086

An assembly program that reads 4 integers, finds the smallest and calculates the sum


It reads the integers just fine and finds the smallest one just fine as well. However, it gives wrong results for sums > 9.
I am trying to calculate the sum in BH as a decimal. However if I for example ask it to add 9 and 9 it stocks 12 in BH instead of 18.

data segment
    msg db "chiffre: $" 
    petit db "plus petit chiffre: $"
    somme db "somme: $"
    
ends

stack segment
    dw   128  dup(0)
ends

code segment
start:
; set segment registers:
    mov ax, data
    mov ds, ax
    mov es, ax
    
    mov ah, 09h
    mov dl, offset msg
    int 21h
    
    mov ah, 01h
    int 21h  
    
    mov bl, al  ; bl contains the smallest number  
    mov bh,al  
    sub bh,'0'
    
    mov cx,3
    etq:  
        mov ah, 02h
        mov dl,0Dh
        int 21h 
        
        mov ah, 02h   
        mov dl,0Ah
        int 21h 
   
        mov ah, 09h
        mov dl, offset msg
        int 21h
        
        mov ah, 01h
        int 21h
        
        cmp al, bl 
        jb min
        jae reste  ; jump to the end of the loop 
        
        min:
            mov bl, al 
    
    reste:
    sub al,'0'         
    add bh,al    
    loop etq 

Solution

  • The debugger is showing the correct result but does so using hexadecimals.
    Displaying numbers with DOS explains how you can convert your number into a string of decimal characters that you can then display on the screen, so you don't have to interpret the hexadecimal values found in the debug window.

    mov dl, offset msg
    

    This is an error that you should be aware of. The DOS.PrintString function 09h expects the address of the string in the word-sized DX register. You should not only load the low byte DL and trust the high byte DH to contain 0. So write mov dx, OFFSET msg.

       cmp al, bl 
       jb min
       jae reste  ; jump to the end of the loop 
    
    min:
       mov bl, al 
    
    reste:
    

    You can easily avoid having to jump over the assignment of the new minimum. If only you would select the opposite conditional jump, you can replace the pair jb min jae reste by the single instruction jnb reste.

    I see that your program is repeating some instructions. I the below code snippet I have the loop do 4 iterations after a suitable initialization of BX before the loop begins:

      mov  bx, 000Ah  ; BH is sum (0), BL is smallest number (10)  
      mov  cx, 4
    etiquette: 
      mov  ah, 09h
      mov  dx, OFFSET msg
      int  21h
      mov  ah, 01h
      int  21h       ; -> AL = ['0','9']
      sub  al, '0'   ; From ['0','9'] to [0,9]
      cmp  al, bl    ; (*)
      jnb  passer
      mov  bl, al    ; Assign a new minimum
    passer:
      add  bh, al    ; Sum
      mov  ah, 02h
      mov  dl, 13
      int  21h 
      mov  dl, 10
      int  21h
      loop etiquette
    

    (*) Because that smallest number variable BL was initialized at 10 which is greater than any (decimal) digit the user can input, the very first cmp al, bl will already set the below condition and therefore the very first new minimum will get assigned from the very first user input (just like it was in your program).

    The biggest sum that your program can expect is 36 (9+9+9+9). As an alternative approach, and instead of using the methods described in the Q/A for which I provided a link above, you could use next code to display a small number in the range [0,99]:

      mov  al, bh    ; Sum eg. 18
      aam            ; -> AH = AL / 10   AL = AL % 10   eg. AH = 1   AL = 8
      add  ax, '00'  ; Convert into text                eg. AH = '1' AL = '8'
      mov  cx, ax
      mov  ah, 02h
      mov  dl, ch    ; Tens eg. '1'
      int  21h 
      mov  dl, cl    ; Ones eg. '8'
      int  21h