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