Calculator in Assembly Language - Linux x86 & NASM - Division

22,545

You're reading two bytes (characters) into num1 and num2 for your number input. This will generally be a single digit (0-9) that you are typing in and a newline character. When you go to do an operation, you read 2 bytes each into ax and bx, so if num1 was 5 and num2 was 1, ax will be 0xa35 and bx will be 0xa31. You then subtract 0x30 from each and divide, giving 1 in all cases, which you then convert to 0x31 '1' and print.

Now in other cases (add/sub), you're actually loading 4 bytes into eax and ebx. So when you add 5 and 1, you'll get 0xa310a35 in eax and 0x????0a31 in ebx (the ???? comes from whatever happened to be in result.) However, after subtracting 0x30 from each and adding, the lowest byte of eax will 0x06, so you'll print 6 as you ignore what is in the upper bytes.

Share:
22,545
Admin
Author by

Admin

Updated on November 06, 2020

Comments

  • Admin
    Admin over 3 years

    I am making a calculator in assembly language to be executed on an x86 processor.

    Basically, my calculator asks the user to enter two numbers and then to indicate which operation (addition, subtraction, multiplication and division) want to do with them.

    My calculator adds, subtracts and multiplies correctly but is unable to divide. In making a division, I always get 1 as the result.

    Then I leave my application code complete:

    section .data
    
        ; Messages
    
        msg1        db      10,'-Calculator-',10,0
        lmsg1       equ     $ - msg1
    
        msg2        db      10,'Number 1: ',0
        lmsg2       equ     $ - msg2
    
        msg3        db      'Number 2: ',0
        lmsg3       equ     $ - msg3
    
        msg4        db      10,'1. Add',10,0
        lmsg4       equ     $ - msg4
    
        msg5        db      '2. Subtract',10,0
        lmsg5       equ     $ - msg5
    
        msg6        db      '3. Multiply',10,0
        lmsg6       equ     $ - msg6
    
        msg7        db      '4. Divide',10,0
        lmsg7       equ     $ - msg7
    
        msg8        db      'Operation: ',0
        lmsg8       equ     $ - msg8
    
        msg9        db      10,'Result: ',0
        lmsg9       equ     $ - msg9
    
        msg10       db      10,'Invalid Option',10,0
        lmsg10      equ     $ - msg10
    
        nlinea      db      10,10,0
        lnlinea     equ     $ - nlinea
    
    section .bss
    
        ; Spaces reserved for storing the values ​​provided by the user.
    
        opc         resb    2
        num1        resb    2
        num2        resb    2
        result      resb    2
    
    section .text
    
        global _start
    
    _start:
    
        ; Print on screen the message 1
        mov eax, 4
        mov ebx, 1
        mov ecx, msg1
        mov edx, lmsg1
        int 80h
    
        ; Print on screen the message 2
        mov eax, 4
        mov ebx, 1
        mov ecx, msg2
        mov edx, lmsg2
        int 80h
    
        ; We get num1 value.
        mov eax, 3
        mov ebx, 0
        mov ecx, num1
        mov edx, 2
        int 80h
    
        ; Print on screen the message 3
        mov eax, 4
        mov ebx, 1
        mov ecx, msg3
        mov edx, lmsg3
        int 80h
    
        ; We get num2 value.
        mov eax, 3
        mov ebx, 0
        mov ecx, num2
        mov edx, 2
        int 80h
    
        ; Print on screen the message 4
        mov eax, 4
        mov ebx, 1
        mov ecx, msg4
        mov edx, lmsg4
        int 80h
    
        ; Print on screen the message 5
        mov eax, 4
        mov ebx, 1
        mov ecx, msg5
        mov edx, lmsg5
        int 80h
    
        ; Print on screen the message 6
        mov eax, 4
        mov ebx, 1
        mov ecx, msg6
        mov edx, lmsg6
        int 80h
    
        ; Print on screen the message 7
        mov eax, 4
        mov ebx, 1
        mov ecx, msg7
        mov edx, lmsg7
        int 80h
    
        ; Print on screen the message 8
        mov eax, 4
        mov ebx, 1
        mov ecx, msg8
        mov edx, lmsg8
        int 80h
    
        ; We get the option selected.
        mov ebx,0
        mov ecx,opc
        mov edx,2
        mov eax,3
        int 80h
    
        mov ah, [opc]   ; Move the selected option to the registry ah
        sub ah, '0'     ; Convert from ascii to decimal
    
        ; We compare the value entered by the user to know what operation to perform.
    
        cmp ah, 1
        je add
        cmp ah, 2
        je subtract
        cmp ah, 3
        je multiply
        cmp ah, 4
        je divide
    
        ; If the value entered by the user does not meet any of the above 
        ; conditions then we show an error message and we close the program.
        mov eax, 4
        mov ebx, 1
        mov ecx, msg10
        mov edx, lmsg10
        int 80h
    
        jmp exit
    
    add:
        ; We keep the numbers in the registers eax and ebx
        mov eax, [num1]
        mov ebx, [num2]
    
        ; Convert from ascii to decimal
        sub eax, '0'
        sub ebx, '0'
    
        ; Add
        add eax, ebx
    
        ; Conversion from decimal to ascii
        add eax, '0'
    
        ; We move the result
        mov [result], eax
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    subtract:
        ; We keep the numbers in the registers eax and ebx
        mov eax, [num1]
        mov ebx, [num2]
    
        ; Convert from ascii to decimal
        sub eax, '0'
        sub ebx, '0'
    
        ; Subtract
        sub eax, ebx
    
        ; Conversion from decimal to ascii
        add eax, '0'
    
        ; We move the result
        mov [result], eax
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    multiply:
    
        ; We store the numbers in registers ax and bx
        mov ax, [num1]
        mov bx, [num2]
    
        ; Convert from ascii to decimal
        sub ax, '0'
        sub bx, '0'
    
        ; Multiply. AL = AX x BX
        mul bx
    
        ; Conversion from decimal to ascii
        add al, '0'
    
        ; We move the result
        mov [result], al
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    divide:
        ; IN THIS LABEL IS THE ERROR!
    
        ; We store the numbers in registers ax and bx
        mov dx, 0
        mov ax, [num1]
        mov bx, [num2]
    
        ; Convert from ascii to decimall
        sub ax, '0'
        sub bx, '0'
        ; Division. AX = DX:AX / BX
        div bx
    
        ; Conversion from decimal to ascii
        add ax, '0'
        ; We move the result
        mov [result], ax
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        ; ALWAYS PRINTS 1
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    exit:
        ; Print on screen two new lines
        mov eax, 4
        mov ebx, 1
        mov ecx, nlinea
        mov edx, lnlinea
        int 80h
        ; End the program
        mov eax, 1
        mov ebx, 0
        int 80h
    

    The error must be found inside the tag "divide".

    Why do I always get 1 as result of a division?

    I hope that someone with more experience can help me with this.


    Thank you all very much. My calculator finally works. Here is my final code:

        section .data
    
        ; Messages
    
        msg1        db      10,'-Calculator-',10,0
        lmsg1       equ     $ - msg1
    
        msg2        db      10,'Number 1: ',0
        lmsg2       equ     $ - msg2
    
        msg3        db      'Number 2: ',0
        lmsg3       equ     $ - msg3
    
        msg4        db      10,'1. Add',10,0
        lmsg4       equ     $ - msg4
    
        msg5        db      '2. Subtract',10,0
        lmsg5       equ     $ - msg5
    
        msg6        db      '3. Multiply',10,0
        lmsg6       equ     $ - msg6
    
        msg7        db      '4. Divide',10,0
        lmsg7       equ     $ - msg7
    
        msg8        db      'Operation: ',0
        lmsg8       equ     $ - msg8
    
        msg9        db      10,'Result: ',0
        lmsg9       equ     $ - msg9
    
        msg10       db      10,'Invalid Option',10,0
        lmsg10      equ     $ - msg10
    
        nlinea      db      10,10,0
        lnlinea     equ     $ - nlinea
    
    section .bss
    
        ; Spaces reserved for storing the values ​​provided by the user.
    
        opc:        resb    2
        num1:       resb    2
        num2:       resb    2
        result:     resb    2
    
    section .text
    
        global _start
    
    _start:
    
        ; Print on screen the message 1
        mov eax, 4
        mov ebx, 1
        mov ecx, msg1
        mov edx, lmsg1
        int 80h
    
        ; Print on screen the message 2
        mov eax, 4
        mov ebx, 1
        mov ecx, msg2
        mov edx, lmsg2
        int 80h
    
        ; We get num1 value.
        mov eax, 3
        mov ebx, 0
        mov ecx, num1
        mov edx, 2
        int 80h
    
        ; Print on screen the message 3
        mov eax, 4
        mov ebx, 1
        mov ecx, msg3
        mov edx, lmsg3
        int 80h
    
        ; We get num2 value.
        mov eax, 3
        mov ebx, 0
        mov ecx, num2
        mov edx, 2
        int 80h
    
        ; Print on screen the message 4
        mov eax, 4
        mov ebx, 1
        mov ecx, msg4
        mov edx, lmsg4
        int 80h
    
        ; Print on screen the message 5
        mov eax, 4
        mov ebx, 1
        mov ecx, msg5
        mov edx, lmsg5
        int 80h
    
        ; Print on screen the message 6
        mov eax, 4
        mov ebx, 1
        mov ecx, msg6
        mov edx, lmsg6
        int 80h
    
        ; Print on screen the message 7
        mov eax, 4
        mov ebx, 1
        mov ecx, msg7
        mov edx, lmsg7
        int 80h
    
        ; Print on screen the message 8
        mov eax, 4
        mov ebx, 1
        mov ecx, msg8
        mov edx, lmsg8
        int 80h
    
        ; We get the option selected.
        mov ebx,0
        mov ecx,opc
        mov edx,2
        mov eax,3
        int 80h
    
        mov ah, [opc]       ; Move the selected option to the registry ah
        sub ah, '0'     ; Convert from ascii to decimal
    
        ; We compare the value entered by the user to know what operation to perform.
    
        cmp ah, 1
        je add
        cmp ah, 2
        je subtract
        cmp ah, 3
        je multiply
        cmp ah, 4
        je divide
    
        ; If the value entered by the user does not meet any of the above
        ; conditions then we show an error message and we close the program.
        mov eax, 4
        mov ebx, 1
        mov ecx, msg10
        mov edx, lmsg10
        int 80h
    
        jmp exit
    
    add:
        ; We keep the numbers in the registers al and bl
        mov al, [num1]
        mov bl, [num2]
    
        ; Convert from ascii to decimal
        sub al, '0'
        sub bl, '0'
    
        ; Add
        add al, bl
    
        ; Conversion from decimal to ascii
        add al, '0'
    
        ; We move the result
        mov [result], al
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 2
        int 80h
    
        ; We end the program
        jmp exit
    
    subtract:
        ; We keep the numbers in the registers al and bl
        mov al, [num1]
        mov bl, [num2]
    
        ; Convert from ascii to decimal
        sub al, '0'
        sub bl, '0'
    
        ; Subtract
        sub al, bl
    
        ; Conversion from decimal to ascii
        add al, '0'
    
        ; We move the result
        mov [result], al
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    multiply:
    
        ; We store the numbers in registers al and bl
        mov al, [num1]
        mov bl, [num2]
    
        ; Convert from ascii to decimal
        sub al, '0'
        sub bl, '0'
    
        ; Multiply. AX = AL x BL
        mul bl
    
        ; Conversion from decimal to ascii
        add ax, '0'
    
        ; We move the result
        mov [result], ax
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    divide:
    
        ; We store the numbers in registers ax and bx
        mov al, [num1]
        mov bl, [num2]
    
        mov dx, 0
        mov ah, 0
    
        ; Convert from ascii to decimall
        sub al, '0'
        sub bl, '0'
    
        ; Division. AL = AX / BX
        div bl
    
        ; Conversion from decimal to ascii
        add ax, '0'
        ; We move the result
        mov [result], ax
    
        ; Print on screen the message 9
        mov eax, 4
        mov ebx, 1
        mov ecx, msg9
        mov edx, lmsg9
        int 80h
    
        ; Print on screen the result
        mov eax, 4
        mov ebx, 1
        mov ecx, result
        mov edx, 1
        int 80h
    
        ; We end the program
        jmp exit
    
    exit:
        ; Print on screen two new lines
        mov eax, 4
        mov ebx, 1
        mov ecx, nlinea
        mov edx, lnlinea
        int 80h
        ; End the program
        mov eax, 1
        mov ebx, 0
        int 80h
    
    • zwol
      zwol about 12 years
      Even though you're coding in assembly language, you should use the C library to make system calls, and you should have your program entry point be main, not _start.
  • Admin
    Admin about 12 years
    Thank you very much for responding, but I can not fully understand your answer. Could you please write your answer in the form of code? Sorry for the inconvenience.
  • Admin
    Admin about 12 years
    I also try doing this but I get "Floating Comma Exception": ` mov ax, [num1] mov bl, [num2] ; Convert from ascii to decimall sub ax, '0' sub bl, '0' ; Division. AL = DX:AX / BX div bl ; Conversion from decimal to ascii add al, '0' ; We move the result mov [result], al`
  • Gunther Piez
    Gunther Piez about 12 years
    @NicolasObesio: If you only accept single digits as input, you should read only a single byte. Use mov al,[num] and mov [result],al etc. and do all relevant operations only on single bytes.
  • Gunther Piez
    Gunther Piez about 12 years
    @ChrisDodd: I think you nailed it.
  • Alex Gordon
    Alex Gordon over 11 years
    chris great job on this, i didnt know you knew asm!