Search code examples
assemblydosx86-16divisiontasm

Division produces wrong result


I'm new to assembly language, and I have a problem. I'm trying to make a basic assembler program with TASM(DOS) that turns on some LEDs according to the result of an operation. All my operations work, except for division. When I do division, only the first LED turns on, which means that the result is 1 in binary. If I put in 4 for the first number and 2 for the second number the result should be 2. The second led should be on not the first one. Why is my division not working properly?

This is the code:

.model small
.stack 64
.data

Numero1 db 0                
Numero2 db 0                
VariableEspecial db 0       


Mensaje1 db 10,13, "Introduce la primera cifra: -> ", '$'
Mensaje2 db 10,13, "Introduce la segunda cifra: -> ", '$'

Mensaje4 db 10,13, "Otra operacion.. 1 - Si, 2 - No, -> ", '$'
Mensaje7 db 10,13, "Escoge operacion: 1 - Suma, 2 - Resta, 3 - Multiplicacion, 4 - Division, -> ", '$'

.code               
begin proc far

mov ax, @data          
mov ds, ax

Inicio:

    mov ah, 09              
    lea dx, Mensaje1        
    int 21h

    mov ah, 01              
    int 21h

    sub al, 30h             
    mov Numero1, al         

    mov ah, 09              
    lea dx, Mensaje2        
    int 21h

    mov ah, 01              
    int 21h                 

    sub al, 30h             
    mov Numero2, al         

    mov ah, 09              
    lea dx, Mensaje7        
    int 21h

    mov ah, 01              
    int 21h

    cmp al, 31h             
    je Suma

    cmp al, 32h             
    je Resta

    cmp al, 33h             
    je Multiplicacion

    cmp al, 34h             
    je Division

Suma:                       
    mov al, Numero1         
    add al, Numero2         

    jmp Leds                

Resta:                      
    mov al, Numero1         
    sub al, Numero2         

    jmp Leds                

; ------------------------      
    Inicio2:                    
    jmp Inicio                  
; ------------------------

Multiplicacion:             
    mov al, Numero1         
    mul Numero2             

    jmp Leds                

Division:                   
    mov al, Numero1         
    div Numero2             

    jmp Leds                

Leds:                       
    add al, 30h             


    cmp al, 31h     
    je UnLed                

    cmp al, 32h             
    je DosLed               

    cmp al, 33h             
    je TresLed              

    cmp al, 34h             
    je CuatroLed            

    cmp al, 35h             
    je CincoLed             

    cmp al, 36h             
    je SeisLed              

    cmp al, 37h             
    je SieteLed             

    cmp al, 38h             
    je OchoLed              

    cmp al, 39h             
    je NueveLed             

    ;-----------------                      
    Inicio3:                                
    jmp Inicio2                             
    ;-----------------

UnLed:                      
    mov dx, 0378H           
    mov al, 00000001b       
    out dx, al              

    jmp FinalizarOperacion  

DosLed:                     
    mov dx, 0378H           
    mov al, 00000010b       
    out dx, al              

    jmp FinalizarOperacion  

TresLed:                    
    mov dx, 0378H           
    mov al, 00000011b       
    out dx, al              

    jmp FinalizarOperacion  

CuatroLed:                  
    mov dx, 0378H           
    mov al, 00000100b       
    out dx, al              

    jmp FinalizarOperacion  

CincoLed:                   
    mov dx, 0378H           
    mov al, 00000101b       
    out dx, al              

    jmp FinalizarOperacion  

SeisLed:                    
    mov dx, 0378H           
    mov al, 00000110b       
    Out dx, al              

    jmp FinalizarOperacion  

SieteLed:                   
    mov dx, 0378H           
    mov al, 00000111b       
    out dx, al              

    jmp FinalizarOperacion  

OchoLed:                    
    mov dx, 0378H           
    mov al, 00001000b       
    out dx, al              

    jmp FinalizarOperacion  

NueveLed:                   
    mov dx, 0378H           
    mov al, 00001001b
    out dx, al

    jmp FinalizarOperacion  

FinalizarOperacion:         

    mov ah, 09              
    lea dx, Mensaje4        
    int 21h
    mov ah, 01              
    int 21h

    cmp al, 31h             
    mov dx, 0378H           
    mov al, 00000000b       
    out dx, al              

    je Inicio3              

    cmp al, 32h             
    mov dx, 0378H           
    mov al, 00000000b       
    out dx, al              

    je Cerrar               

Cerrar: 
    mov ah, 4ch             
    int 21h                 

    begin endp              
    end

Solution

  • There is an issue with the way you are doing division. You are trying to divide the 8-bit number in AL(Numero1) by an 8-bit value (Numero2).

    The thing you have to be careful with is that the DIV instruction divides all of AX by the 8-bit(byte) operand. You set AL to Numero1 but you didn't make sure that the AH register was 0. By not doing this you are dividing AX which likely has junk in AH making your division operation work with the wrong number.

    The Instruction Set Reference says this about DIV

    Unsigned divide AX by r/m8, with result stored in AL = Quotient, AH = Remainder.

    You need to explicitly set AH to 0 in your case. You can do that with mov ah, 0, or use the preferred alternative xor ah, ah. Both set AH to zero.

    Your division code looks like this:

    Division:                   
        mov al, Numero1         
        div Numero2             
        jmp Leds
    

    It should look something like:

    Division:
        xor ah, ah                   
        mov al, Numero1         
        div Numero2             
        jmp Leds  
    

    This ensures that the division is 00000000:AL(Numero1) divided by Numero2