News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Simple Arithmetic Input 8086

Started by krikara, November 22, 2010, 09:48:38 AM

Previous topic - Next topic

krikara

That makes sense, but what happens in the case of

"-100 + -200"
or
"100 + -200"

How will the program know when the operator is actually an operator and not the sign of the number?
I think it has to be done manually where it reads a number, then an operator, and then a number, but I don't know how to
code that  :'(

Are there certain instructions that I should look up?
I have no idea where to start with this...

dedndave

yes - that is an advantage of using a parser loop   :P
there are a number of ways to write it
many will tell you that LODSB is not a fast instruction (some say never use it), but this might be a good place to use it
speed is not a real issue, here, and the instruction is small and simple and increments the index for you   :bg

start with the line input
let's find out what Kip's function does
does it limit and/or return the input string length ???

dedndave

here we are...
ReadString
Waits for/reads an ASCII string.
Input: EDX contains the offset to store the string
ECX contains max character count
Output: EAX contains number of chars input


the docs i have don't tell me if he terminates the string with a nul   :bg

krikara

From my understanding, Strings are in BYTE

so lodsb would be the appropriate instruction since it loads BYTE into AL. However
if my input is "5+-6"
it should load "5" into eax
load "+" into al
load "-6" into eax.

What instructions should I use to separate the string? And also, the string is in BYTE, but I want to store part of the
string in EAX. Does that mean is use lodsd? How would I go about doing that as well.

EDIT: To read a string, I would use  call ReadString

I believe call ReadString stores into the al register.
This is how ReadString looks

Call args:  EDX points to the input buffer
            ECX max number of non-null chars to read

Return arg: EAX = size of input string.

Example:

.data
MAX = 80                     ;max chars to read
stringIn BYTE MAX+1 DUP (?)  ;room for null

.code
      mov  edx,OFFSET stringIn
      mov  ecx,MAX            ;buffer size - 1
      call ReadString
(Taken from Irvine lib help)


dedndave

well - whether you choose to use LODSB or not...
a loop can read each character, one by one (LODSB loads a single byte into AL, then increments ESI)
basically, you want to find the address in the buffer where each element begins and ends

let's start by putting the count in ECX
so, you load a byte - see if it is part of a number
the first character may be a +/- sign, or it may be a numeric digit
there may be up to 10 digits for a 32-bit number
after the first character, only numeric digits may be allowed
if a non-numeric character is found, you have found the end address of the first element
it may be a space, or it may be the operator character
if it is a space, ignore it
as each character is parsed, decrement the count in ECX
if ECX = 0, you are done
if not, return to the top of the loop and continue parsing

that is the basic idea of a parser loop
(ASCII numeric digits are 30h - 39h,  representing 0 - 9)
(space = 20h)

jj2007

Quote from: dedndave on November 22, 2010, 12:15:10 PM
a loop can read each character, one by one (LODSB loads a single byte into AL, then increments ESI)
basically, you want to find the address in the buffer where each element begins and ends

See reply #2 above for code that gets you the buffer. Ashan, did you install the Masm32 package???

dedndave

QuoteAshan, did you install the Masm32 package???

wrong thread, Jochen   :bg

i have helped Krikara before - he tries hard to write his own code   :U

jj2007

Quote from: dedndave on November 22, 2010, 01:11:53 PM
QuoteAshan, did you install the Masm32 package???

wrong thread, Jochen   :bg

i have helped Krikara before - he tries hard to write his own code   :U


Apologies to Krikara. However, the code in reply #2 of this thread is indeed the best start for a parser. You need to read a full line, then use lodsb (=mov al, [esi] combined with inc esi) to split the line into its components.

hutch--

krikara,

You are going to have to specify how the text is entered that is evaluated by a parser. You can have negative or positive numbers but there must be some way of differentiating sign notation from the operator between the two numbers.

-100 * +650

If you allow both positive and negative sign notation then you must have some space or other means of distinguishing between "-100" "*" and "+650".

Ideally you would use a table based parser and that can be done with the masm32 library but I am not sure how you would do it with Kip's library unless it has a dedicated capacity to do this type of stuff. Essentially what you need is a tokeniser that will separate text based on the delimiting characters between the numbers.

What you cannot do wihout a far more complex parser is allow input text like this.

-100*+650.

There is a trick if you did not have to run sign notation, replace all of the operators with an extra space each side so that "+" becomes " + " etc ....
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

krikara

Hey I found a way to do it, but it doesn't use lobsb. Although maybe it could.... I'm not exactly sure.
What is the difference between mov al, string[esi] and lodsb?

Anyways, here is the pseudocode/logic for what I am going to do. I am pretty sure this logic works, however I didn't code it yet, so I haven't tested it.

QuoteFirst
Check the first character. It can either be a sign or a number. If it is a sign, then a number is immediately after.

Read number:
Keep reading the numbers until a sign is reached. Store that number into num1

This sign is an operator sign, so store it into operator

Next, check for a sign again. Store that number into num2.

Basically, the only problem is storing the numbers correctly. But I think I have that solved as well. Just multiply the total number by 10 everytime.
So say the number is 123.
The program reads 1 first. Program knows that there is another number next, so it does 1*10 +2 = 12. Then there is a 3 next. So program does 12*10 +3 = 123. And it stops because that is the end of the number.
So far things are looking good and the coding itself seems fairly simple.

Hopefully, I can get this done soon. Also, it would be good to know the difference between lodsb and mov al, string[esi]  :D

jj2007

Quote from: krikara on November 23, 2010, 07:22:24 AM
Also, it would be good to know the difference between lodsb and mov al, string[esi]  :D

lodsb combines two actions in one instruction:
mov al, [esi]
inc esi


It is not the best instruction for an ultrafast innermost loop, but for parsing it's just excellent.
Note there variants that you don't need here:
lodsw
mov ax, [esi]
add esi, 2

lodsd
mov eax, [esi]
add esi, 4


See \masm32\help\opcodes.chm for more info.

krikara

Alright, I got the program compiling correctly performing all the arithmetic perfectly. Now I am just going to have some IllegalArgumentErrors for bad input.

And then I will experiment with lodsb :D

Also, should I upload the program for any future people that want to view a basic arithmetic calculator?

jj2007

Quote from: krikara on November 23, 2010, 10:16:53 AM
Also, should I upload the program for any future people that want to view a basic arithmetic calculator?

Sharing code is always a good thing: Zip it and attach the archive, using "Additional Options" in the lower left of the Reply window.
But can you include all needed non-Masm32 libraries, legally speaking? Otherwise most people won't be able to use it...

dedndave

to use or not use LODS instructions is one, mainly, of speed
how fast do you need to parse a single line of text ? - lol
at any rate, i think it is a good idea for beginners to familiarize themselves with the string instructions
and, LODSB is one of the simplest ways to do that - another would be STOSB/REP STOSB
you should also read up on the CLD and STD instructions, noting that in win32, the flag is usually cleared for you

as for parsing the line, i would take the approach that it is always a 3 element line
so, i would parse through to the end of the first element, then find the simple one-char operator (second element)
after that, whatever is left is the third element

as Hutch mentioned, this type of parser can be a little complicated because numeric signs and operators use the same chars
and that would be especially true if there were more elements on the line
but, take the 1-2-3 element approach and it won't be too bad

krikara

Hmm

I have been debugging for about half an hour now and can't seem to figure out why my program always calls my BadInput function even when there isn't bad input.
The program itself does all the arithmetic correctly, but I am trying to make it so the program catches bad input. For some reason however, it sees the good
input as bad input too and I just don't understand why.

I;'ll upload what I have in zip. If someone could help soon, that would be awesome.

The only time I call BadInput is in checkElement near the begining.
And all Badinput does is display an error msg.



EDIT UPDATE:

I commented out the call BadInput
and it still displays the error message no matter what.
What is going on?!?!

EDIT 2 :
WOW I fixed it. Just because I didn't put ret at the end of my Operations function, it went to the next function (BadInput). I didn't
even know that was possible. Im pretty sure in high level programming languages that functions dont jump to other
functions if you dont return. Sigh... I will upload the final in the next post