Hello.  I urgently need a program in assembler, for a x86, in Linux.
The program has to do the following:
- Read from the keyboard a function of x.  Example: "x+2-x^3*9"
  *) The function has to be in the form of dododod (d=digit [0-9], 0=operator [+,-,*,/,^]),
  *) Therefore, it does not admit 2 operators or 2 digits together (like "12^-x"),
  *) No error handling needed, it is assumed that the entered values are correct
- Read from the keyboard the value of x. Example: "1"
- Show the result of the function with that value of x (in the example it would be "-6")

I'm really newby to assembler programming so I would really preciate if someone could give me a hand "for the love of the game".

Best regards!
Posted on 2006-07-24 16:40:56 by Anixandro
Please read the community rules. This is not _we_do_your_homework_ forum.
Posted on 2006-07-24 16:49:04 by arafel

I'm really newby to assembler programming so I would really preciate if someone could give me a hand "for the love of the game".


You have to ask a question before we can attempt to help you. Also, you have to be a little more specific than just laying out your requirements.

Now, I have a few questions for you.

1) How much of the source is "complete"???
2) Which part's' are you having trouble with???
3) Why the urgency if you are "new to assembly language"???
Posted on 2006-07-24 19:57:48 by SpooK
Sorry about that, I was not familiarized with the rules since I'm new to the forum.

Let me reformulate the question then:
Does anyone have an example or a piece of code that can help me or lead me to the solution?

Any help will be appreciated.
Posted on 2006-07-24 20:14:14 by Anixandro
1) How much of the source is "complete"???
What i have is what follows:


.data
    function: .string "                  "
    valx: .int 0
    t_int: .string "%d"
    t_str: .string "%s"
    title1: .string "Enter the function: "
    title2: .string "Enter the value of x: "
    linefeed: .string "\n"
.text
    .global main
main:
    pushl $title1  #push in the stack the first title
    pushl $t_str    #push in the stack the type of value
    call printf      #print the output
    addl $8,%esp  #clear the stack

    movl $3,%eax
    int $0x80        #call the interupt for printing

    pushl $function #push in the stack the function variable
    pushl $t_str      #push in the stack the type of value
    call scanf        #read the input
    addl $8,%esp    #clear the stack

    pushl $title2    #push in the stack the second title
    pushl $t_str    #push in the stack the type of value
    call printf        #print the output
    addl $8,%esp  #clear the stack

    movl $3,%eax
    int $0x80        #call the interrupt for printing

    pushl $valx      #push in the stack the receiving variable
    pushl $t_int      #push in the stack the data type
    call scanf        #read the input
    addl $8,%esp    #clear the stack

    pushl $linefeed  #push in the stack the string of linefeed
    pushl $t_str      #push in the stack the data type
    call printf        #print the linefeed
    addl $8,%esp  #clear the stack

    movl $3,%eax
    int $0x80        #call the interruption for printing

    ret
    #this is the section where I want to parse char by char the input stored in the "function" variable, but I don't
    #know how.  Then I would have to calculate the result of the function and show the output. 


2) Which part's' are you having trouble with???
I'm having trouble parsing the string of the formula input.  I can't find the way to read character by character the string, to put the operands and the operators in a stack for the calculations.  As you can see, I'm using AT&T notation and what I'm doing to compile the code is the following, in Red Hat:
  *) Open a terminal
  *) Go to the folder which contains the code
  *) Execute the next command "gcc -o "

3) Why the urgency if you are "new to assembly language"???
The urgency is that my teacher is kinda crazy.  He believes in the investigative capabilities of his students to solve any problem he can think of, while he does not have a clue of the assembly language.  I'm in summer so the period of classes is really short and he gave us a week to get the project done.

Thanks in advance.
Posted on 2006-07-24 20:36:48 by Anixandro
Well.., there are plenty of algorithms for making an expression evaluator. Here is one of the simplest approaches:
(assuming the conditions you have stated are preserved)

1) Get the expression (for example x+2-x^3*9).
2) Get the value of 'x'.
3) Construct new expression by converting any ASCII representation of a digit to it's binary form. Replace any occurrence of 'x' with appropriate value.

So from x+2-x^3*9 you will get something like this (hexadecimal representation):
00000001 + 00000002 - 00000001 ^ 00000003 * 00000009

4) Search for operator with a higher mathematical precedence.
5) Apply the operation on the nearby digits.
6) Reconstruct the expression.
7) Repeat last three steps

E.g.:
00000001 + 00000002 - 00000001 ^ 00000003 * 00000009
00000001 + 00000002 - 00000001 * 00000009
00000001 + 00000002 - 00000009
00000003 - 00000009
FFFFFFFA



The urgency is that my teacher is kinda crazy.Šnbsp;


He surely is. Teaching AT&T syntax.... eeeewww!
Posted on 2006-07-24 21:37:55 by arafel
I do know the step by step algorithm, the codification is what I'm struglin with.  Haven't advanced much... how do I get the first digit from the function?
Posted on 2006-07-24 22:24:56 by Anixandro
By the way, Intel notation would be great too.
Posted on 2006-07-24 23:00:51 by Anixandro
There is nothing really to "codify", as the resultant string returned from scanf should be in ASCII format.

arafel touched upon the fact that you have to convert "any ASCII representation of a digit to it's binary form", so this would be your next step.

Personally, for a simple project like this that requires no error-checking, I would go for a counter mechanism...


;!!!!!NASM syntax!!!!!

;Parse the function input
    mov ebx,DWORD function ;ASSUMED TO BE ALIGNED TO AN "EVEN" ADDRESS
    mov al,BYTE
    cmp al,0
    jnz continue_parsing
    ret ;reached the string "null terminator" (\0)... so return/exit

;Test if EBX is odd (operation) or even (digit)
continue_parsing:
    test bl,1  ;Test if EBX is odd or even
    jnz process_operation ;Even = Process a "Digit", Odd = process an "Operation"

process_digit:
;todo: check for ASCII byte value between 30h-39h
;  Yes-> Subtract 30h from the byte value, and use for later
;  No-> Fail/Exit (no error handling)

process_operation:
;todo: check for ASCII values of "+-*/^..." in order (like a switch statement)
;  Found-> Process that operation into an "order of operation" list
;  Not Found -> Fail/Exit (no error handling)

inc ebx
jmp parse


Note that EBX *should* be BYTE aligned and hence on an "even address". So each "Digit" should be on an even BYTE address (dododo)... and each "Operation" should be on an odd BYTE address (dododo).

Just fill in the blanks with your own ideas on how to process ASCII code and the "order of operations" list.

Another thing I noticed with your code, is the unnecessary use of "pushl $t_str" in your printf routines. The strings are already in "%s" format (ASCII text with a null-terminator), so there is no need to add this extra step. You *do* need it for scanf though, as that is how the function defines the input.
Posted on 2006-07-25 01:21:37 by SpooK
Hello, guess what? I decided to move to Intel syntaxis.
I have the following code:



    title1:    db 'Enter the function: ',10
    title1Len equ $-title1


    global main

main:
    mov eax, 4          #system output
    mov ebx, 1          #standard output
    mov ecx, title1    #variable to print
    mov edx, title1Len #length to print
    int 80h                #system interrupt

    mov eax, 3          #system input
    mov ebx, 0          #standard input
    mov ecx, function #variable to receive the input
    mov edx, 25        #max length to receive
    int 80h                #system interrupt

    mov eax,     #store in eax the first digit
    mov ebx, #store in ebx the second digit
    add eax, ebx              #add the two digits

    mov , eax    #store the result in 'digit' variable

    mov eax, 4          #system output
    mov ebx, 1          #standard output
    mov ecx, digit      #variable to print
    mov edx, 1          #length to print
    int 80h              #system interrupt

    mov eax, 1  #finalitation of the program
    mov ebx, 0  #finalitation of the program
    int 80h      #finalitation of the program

    ret


    function resb 25
    function resb 1


As you can see, I want to display the result of adding the first two digits entered in the function (just for testing purposes, in the main problem you aren't supposed to enter a digit followed by another).  The problem is that when I enter in the function "12", it is displaying a "c" as te result of the sum (1+2=third letter from the alphabet -> c); when I enter "23", it is displaying an "e" as the result of the sum; etc etc.  What am I doing wrong? What do I have to change to display the correct value?
Posted on 2006-07-25 17:01:22 by Anixandro
Please study an ASCII Chart to understand what you are working with. You are confusing a string representation of a digit (ASCII) with a binary representation that a computer uses for mathematical operations.

If you notice the chart from the link above, '1'(31h) + '2'(32h) = 'c'(63h). As well as '2'(32h) + '3'(33h) = 'e'(65h).

This means you are not converting the ASCII Characters to Binary before performing mathematical operations, which was mentioned multiple times.

If you checked for a value between 30h and 39h (valid ASCII representation of numbers 0 through 9), and then subtracted 30h from that value... it would give you the converted binary number you need (i.e. '1'(31h) - "ASCII Digit Base"(30h) = 1(01h) ). In order to printf that number, you would simply add %i to the string (and the accompanying variable), and printf will automatically convert that Binary Digit 3(03h)/5(05h) back to an ASCII representation '3'(33h)/'5'(35h).

In short, you *really* need to study the differences between ASCII and Binary... or you will not make your deadline.

In order to help you on your way, I will post a generic "quick fix" (no error checking or optimization) of your code, study it until it "clicks"...



    mov al, BYTE      #store in al the first digit (ASCII = 1 Byte)
    mov ah, BYTE    #store in ah the second digit (ASCII = 1 Byte)
    sub al, 30h                #convert the first ASCII digit to Binary form
    sub ah, 30h                #convert the second ASCII digit to Binary form
    add al,ah                  #add the two digits

    mov BYTE,al          #store the result in 'digit' variable

Posted on 2006-07-25 18:20:19 by SpooK