Jump to content
Welcome, welcome! Come in and register, and have some developer coffee. 👨‍💻 ×

A simple calculator (CLI)


Recommended Posts

This is an exercise for everyone!

 

Challenge

Currently it just supports addition of two numerical values, not yet complete for other arithmetic operation.

Why not take this as an exercise in Assembly programming and complete the function for subtraction, multiplication and division?

 

Source Code

format PE64 Console
include 'win64axp.inc'


.code

start:
        sub     rsp,8

        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     [stdin],eax
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     [stdout],eax


        ; outer loop - command
        invoke  WriteConsole,[stdout],addr sError,sErrorSz,addr outSz,0
        invoke  ReadConsole,[stdin],buff,1024,addr count,0
        mov     edi,buff
        ; ? cmds
        cmp     byte [edi],'+'
        je      HANDLEADD
        cmp     byte [edi],'-'
        je      HANDLESUB
        cmp     byte [edi],'*'
        je      HANDLEMUL
        cmp     byte [edi],'/'
        je      HANDLEDIV
        jmp     error



        jmp     error

error:
        mov rcx,sError
        invoke WriteConsole,[stdout],addr sError,sErrorSz, addr count, 0

        jmp clear
HANDLEADD:
        push    r12
        push    r13


        invoke  WriteConsole,[stdout],addr sAdd,sAddSz,addr outSz,0
        invoke  ReadConsole,[stdin],buff,1024,addr count,0
    ;    mov eax,buff
     ;   push buff
    ;    mov by
    ;    push qword [eax]
    ;    push count-2

        call convert
        mov r12d, eax
        ;movzx   r12, byte [buff]
        ;sub r12, 48

        ; ask for second number
        invoke  WriteConsole,[stdout],addr sAdd2,sAdd2Sz,addr outSz,0
        invoke  ReadConsole,[stdin],buff,1024,addr count,0

        ;movzx   r13,byte [buff]
        ;sub r13, 48
        call convert
        mov r13d,eax

        ; add it!
        add     r12d,r13d

invoke wsprintf,result,'%d',r12d
invoke  WriteConsole,[stdout],result,6,addr outSz,0


        pop     r13
        pop     r12
        jmp     clear

convert:
    xor eax,eax
    lea ebx, [buff]
.redo:
    movzx ecx, byte [ebx]
    inc ebx
    cmp ecx, '0'
    jb .done
    cmp ecx, '9'
    ja .done
    sub ecx, '0'
    imul eax, 10
    add eax,ecx
    jmp .redo
.done:
    ret




HANDLESUB:
        invoke WriteConsole,[stdout],addr sAdd,sErrorSz, addr count, 0

        jmp     clear
HANDLEMUL:
        invoke WriteConsole,[stdout],addr sAdd,sErrorSz, addr count, 0

        jmp     clear
HANDLEDIV:
        invoke WriteConsole,[stdout],addr sAdd,sErrorSz, addr count, 0

        jmp     clear
equal:
        invoke WriteConsole,[stdout],addr sAdd,sErrorSz, addr count, 0

        jmp     clear
notequal:
        invoke WriteConsole,[stdout],addr sAdd,sErrorSz, addr count, 0

        jmp     clear
clear:
        xor rcx,rcx
        xor rdi,rdi
        xor rsi,rsi
        xor eax,eax
        xor ecx,ecx
        jmp start
.data
        buff    rb 1024
        buff2   rb 1024
        result  rb 64
        count   dd ?
        outSz   dd ?
        count2  dd ?
        stdin   dd ?
        stdout  dd ?
        pMath   dd 0

        sError          db 'Try +, -, *, /',10,0
        sErrorSz        = $ - sError
        sEqual          db 'It is equal',10,0
        sEqualSz        = $ - sEqual
        sNotEqual       db 'Not Equal',10,0
        sNotEqualSz     = $ - sNotEqual
        sAdd            db 'First number to add?',10,0
        sAddSz          = $ - sAdd
        sAdd2           db 'Second number?',10,0
        sAdd2Sz         = $ - sAdd2
        sMul            db 'First number to multiply?',10,0
        sMulSz          = $ - sMul
        sMul2           db 'Second number to multiply?',10,0
        sMul2Sz         = $ - sMul2
        sSub            db 'First number to subtract?',10,0
        sSubSz         = $ - sSub
        sSub2           db 'Second number to subtract?',10,0
        sSub2Sz         = $ - sSub2
        sDiv            db 'First number to divide?',10,0
        sDivSz          = $ - sDiv
        sDiv2           db 'Second number to divide?',10,0
        sDiv2Sz         = $ - sDiv2

.end start

This Assembly code if compiled using FASMW, will generate a 64-bit binary executable.

 

Clarification

The code was originally done by someone, but I went further and make it works (for addition of two numbers).

Note that the routine for conversion from string to integer was modified from example code on Stack Overflow.

 

Screenshot

Screenshot showing the simple calculator in action:

C01.thumb.JPG.8aa5f61268d06530af478ef5423b81b1.JPG

 

Download

Sign in to download CALC.zip (package includes CALC.EXE and CALC.ASM).

 

CALC.zip

  • Like 1
Link to post
Share on other sites
Posted (edited)

Some general explanation to the CPU instructions. 😛

        xor rcx,rcx
        xor rdi,rdi
        xor rsi,rsi
        xor eax,eax
        xor ecx,ecx
        jmp start

XOR two registers is to clear the value of the said register, because 123 XOR 123 = 0. This is very common in Assembly language.

Registers that start with R are 64-bit. Registers that start with E are 32-bit. Registers without either R or E prefix are 16-bit.

JMP is self-explanatory, jump to the label "start".

 

invoke 

This is not a CPU instruction, but I believe it is a macro set by FASM to simplify making calls to Win32 API.

 

    cmp ecx, '0'
    jb .done
    cmp ecx, '9'
    ja .done

In Assembly language, CMP is commonly used as conditional instruction, in essence it is IF ECX == '0' THEN......

JB is jump if the value is below '0'. JA is jump if the value if above '9'.  Easy right?

 

    mov r13d,eax

MOV is another most common CPU instruction, to assign a value to a register, or to copy from one memory buffer to another.

I, too, am learning about modern Assembly language. 

 

Edited by FlierMate
  • Love 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...