Jamie Jackson
Jamie Jackson

Reputation: 96

Can't figure out printf function in assembly x86 and working with operands

I'm already nervous about posting this question, but here it goes. Im attempting to design an Assembly Program to take in two integers, then take in an operand (*, +, or ^). Then, depending on the operand, the program will perform the arithmetic sequence based on the operand chosen. The output has to look exactly like this, lets say the user inputs 5, then the user inputs 6, and lastly the user inputs a *, the program must print out

OP 5 * 6 = 30

Now, I cannot grasp the concept of printf for some reason, so my printfunction at the bottom is my ridiculous way of attempting to print this out. If someone could explain to me how printf works, id love to hear it! I have very basic knowledge of the stack. Also, I do not have the exponential function in this, because I have no idea how to do it in assembly language. And lastly, I have a non program related question for the true computer gods out there...I absolutely hate assembly language, I have trouble writing basic operations in this language. I loved working in C, CPP, and Java...is this langauge absolutely necessary to survival in a programmers day to day, or is this a history lesson on how people made fire before they had lighters? Anyway, any answers to any questions are welcome, and thank you in advance.

;program to add, multiply, or give the power of a number

%include "asm_io.inc"


segment .data 


prompt1 db    "Enter a number: ", 0        ;prompts
prompt2 db    "Enter another number: ", 0
prompt3 db    "Enter an operand", 0
prompt4 db    "OP ", 0    ;idiotic prompts for printing
prompt5 db    " = ", 0    ;another printing prompt

segment .bss

num1  resd 1    ;variable for 1st number
num2  resd 1    ;variable for 2nd number
op    resd 1    ;variable for operand


segment .text

    global  asm_main
asm_main:
    enter   0,0               ; setup routine
    pusha

    restart:
        mov     eax, prompt1      ; print out prompt
        call    print_string
        call    print_nl

        call    read_int          ; read integer
        mov     [num1], eax       ; store into num1
        call    print_nl

        mov     eax, prompt2      ; print out prompt
        call    print_string
        call    print_nl

        call    read_int          ; read integer
        mov     [num2], eax     ; store into num2
        call    print_nl

        mov     eax, promtp3    ;print out prompt
        call    print_string
        call    print_nl

        call    read_char       ;read operand and dispose of null
        call    read_char
        mov     [op], eax       ;store operand in [op]
        call    print_nl

        cmp     [op], '*'       ;operand comparison
        jne     jmp1
        call    mulFun
        jmp     restart

jmp1:   cmp     [op], '+'       ;operand comparison
        jne     jmp2
        call    sumFun
        jmp     restart

jmp2:   cmp     [op], '^'       ;operand comparison
        jne     jmp3
        call    expFun
        jmp     restart

jmp3:   cmp     [op], 'e'       ;exit function
        je      end1

end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    call    print_nl          ; pr
    popa
    mov     eax, 0            ; return back to C
    leave
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mulfun:                     ;multiplication function
    mov     ebx, [num1]
    mov     ecx, [num2]
    imul    ebx, ecx
    jmp     printFun

sumFun:                     ;sum function
    mov     ebx, [num1]
    mov     ecx, [num2]
    add     ebx, ecx
    call    printFun


printFun:                   ;printing function
    mov     eax, [prompt4]
    call    print_string
    mov     eax, [num1]
    call    print_string
    mov     eax, [op]
    call    print_string
    mov     eax, [num2]
    call    print_string
    mov     eax, [prompt5]
    call    print_string
    mov     eax, ebx
    call    print_string
    call    print_nl
    ret

Upvotes: 2

Views: 1370

Answers (1)

Michael Petch
Michael Petch

Reputation: 47593

Everywhere I found an issue I have added *** in the comments. A few things to note:

  • You had typos in some of your labels
  • NASM is case sensitive, so mulfun is not the same as mulFun.
  • If you have an instruction taking one or more operands that doesn't involve a register (for src or destination) but references memory - you need to specify the size of the memory operand. For example cmp [op], '+' the size of the data [op] refers to has to be specified so you prefix it with the size. Size can be byte, word, dword. You are comparing a single character so the size would be byte . The code should have looked like this cmp byte [op], '+'
  • If you have a variable and you do mov eax, varname this moves the address of varname to EAX. If you want to move the contents of varname you have to surround it with square brackets like mov eax, [varname] . When dealing with string addresses and the print_string routine you need to pass the address of the string in EAX, not the contents. So leave out the brackets.
  • If you use call to call a function, your function should end with a ret.
  • Don't jmp to a function, use call
  • If you want to print a character don't use print_string, use print_char. Place the character in EAX
  • If you want to print an integer don't use print_string, use print_int. Place the integer in EAX

The revised code is as follows:

;program to add, multiply, or give the power of a number

%include "asm_io.inc"

segment .data

prompt1 db    "Enter a number: ", 0        ;prompts
prompt2 db    "Enter another number: ", 0
prompt3 db    "Enter an operand", 0
prompt4 db    "OP ", 0    ;idiotic prompts for printing
prompt5 db    " = ", 0    ;another printing prompt

segment .bss

num1  resd 1    ;variable for 1st number
num2  resd 1    ;variable for 2nd number
op    resd 1    ;variable for operand


segment .text

    global  asm_main
asm_main:
    enter   0,0                 ; setup routine
    pusha

    restart:
        mov     eax, prompt1    ; print out prompt
        call    print_string
        call    print_nl

        call    read_int        ; read integer
        mov     [num1], eax     ; store into num1
        call    print_nl

        mov     eax, prompt2    ; print out prompt
        call    print_string
        call    print_nl

        call    read_int        ; read integer
        mov     [num2], eax     ; store into num2
        call    print_nl

        mov     eax, prompt3    ;print out prompt
                                ;*** Typo - promtp3 changed to prompt3
        call    print_string
        call    print_nl

        call    read_char       ;read operand and dispose of null
        call    read_char
        mov     [op], eax       ;store operand in [op]
        call    print_nl

        cmp     byte [op], '*'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp1
        call    mulFun
        jmp     restart

jmp1:   cmp     byte [op], '+'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp2
        call    sumFun
        jmp     restart

jmp2:   cmp     byte [op], '^'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp3
;        call    expFun         ;*** This expFun function doesn't exist so
                                ;*** don't call it so we can compile and link
        jmp     restart

jmp3:   cmp     byte [op], 'e'  ;exit function
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        je      end1

end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    call    print_nl          ; pr
    popa
    mov     eax, 0            ; return back to C
    leave
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mulFun:                     ;multiplication function
                            ;*** NASM is case sensitive - changed mulfun to mulFun
    mov     ebx, [num1]
    mov     ecx, [num2]
    imul    ebx, ecx
    call    printFun        ;*** Call printFun, don't 'jmp' to it
    ret                     ;*** Since mulfun was called, we use 'ret' to return

sumFun:                     ;sum function
    mov     ebx, [num1]
    mov     ecx, [num2]
    add     ebx, ecx
    call    printFun
    ret

printFun:                   ;printing function
    mov     eax, prompt4    ;*** We want the address of prompt4, not what is at prompt4
                            ;*** Remove the brackets from [prompt4]
    call    print_string
    mov     eax, [num1]
    call    print_int       ;*** Use print_int to print an integer, not print_string
    mov     eax, [op]
    call    print_char      ;*** Use print_char to print a char, not print_string
    mov     eax, [num2]
    call    print_int       ;*** Use print_int to print an integer, not print_string
    mov     eax, prompt5    ;*** We want the address of prompt5, not what is at prompt5
                            ;*** Remove the brackets from [prompt5]
    call    print_string
    mov     eax, ebx
    call    print_int       ;*** Use print_int to print an integer, not print_string;
    call    print_nl
    ret

I will leave it up to the original poster to develop the expFun function. For the time being I have commented it out so the existing code can be assembled, linked, and run.

You can use printf but I think the long way can teach a few things too, and I have excluded a discussion of printf from my answer. Your instructor, course material, teacher assistant would be a good place to start with your other questions.

This answer is being provided to get your program into a usable state so that you can proceed with the assignment. In my opinion the original question is too broad. If further help is needed it is probably best to ask a new question with a specific issue.

Upvotes: 4

Related Questions