amXor

Blogging about our lives online.

3.02.2010

Simple RPN Calculator

Reverse Polish Notation is a simple method of calculation that was used extensively in scientific calculators such as the HP 32S but has fallen out of use somewhat these days. I have decided to implement an RPN calculator in Assembly Language to test what I have learned so far. Here is version 0.01 that only adds and subtracts, just to give a rough layout of how it will work.
.section .data
  expr_length:  .int 128
  ADD:          .ascii "+"
  SUB:          .ascii "-"
  null:         .ascii "\0"
  disp_float:   .ascii "%f\n\n\0"
.section .bss
  .lcomm expr, 128

.section .text
.globl main

main:
    finit
1:
    leal    null, %esi          # Clear the expr buffer
    leal    expr, %edi
    movl    expr_length, %ecx
    cld
    lodsb
    rep     stosb               #__
    addl    $4, %esp
    pushl   stdin               # char * fgets (char * str, int len, * stream)
    pushl   $64
    pushl   $expr
    call    fgets
    addl    $12, %esp

    movb    ADD, %ah            # Test For Operators in expr
    movb    expr, %bh           # and jump to code if operator found
    cmp     %ah, %bh
    je      addFloat
    movb    SUB, %ah
    cmp     %ah, %bh
    je      subFloat

    pushl   $expr               # Defaults to a number
    call    atof                # double atof (const char * str)
    addl    $4, %esp            # pushes a float into st(0) from string
    jmp 1b


addFloat:
    faddp
    fstpl   (%esp)
    pushl   $disp_float
    call    printf
    addl    $8, %esp
    jmp     1b

subFloat:
    fsubrp
    fstpl   (%esp)
    pushl   $disp_float
    call    printf
    addl    $8, %esp
    jmp     1b

    movl $1, %eax           # All roads jump back to 1 so we never get here
    movl $0, %ebx
    int $0x80
And here's how it looks in action:
$./rpn
14.5
88
+
102.500000

12.3
6.6
-
5.700000
It took some digging to figure out how to load a value into the FPU from a string and the "atof" C library function seemed to be the easiest. All it needs is a string pointer on the stack ("$expr" in the code) and it does it's best to convert it to a float and push it onto the FPU stack - fairly painless. The operator test needs some work since it will always give a false positive if you punch in a signed value. Punching in -12 causes the calculator to run the subtraction code and disregards the number you typed in, not ideal. Other todos: 1. Pull the display code out of the calculations, this should be generic. 2. Push the result back onto the stack so you can use it in following calculations. 3. Filter the input somewhat.

No comments:

Post a Comment

Twitter

Labels

Followers

andyvanee.com

Files