Author Topic: nasm problems calling C functions - printf and scanf  (Read 7156 times)

Offline jdubya

  • Jr. Member
  • *
  • Posts: 7
nasm problems calling C functions - printf and scanf
« on: November 10, 2013, 07:52:19 PM »
I'm working on a small project that gets a name and a number from user input.  I want to add a number (eg. 5555) to the user entered number and then tell the user the answer. I having trouble and could use some help. Here's the code:

Code: [Select]
SECTION .data

        askName:   db "Enter your name: ",0
        askNum:    db "Enter an integer no more than four digits: ",0
        formats:   db "%s", 10, 0    ; string with line feed
        formatsnlf db "%s",0          ; string w/o line feed
        formatd:   db "%d", 10, 0    ; integer with line feed
        formatdnlf db "%d",0          ; integer w/o line feed

        fResult:  db "Thank you %s. After the addition to your number the sum is now: %d",10, 0

        ; arrays
        number: times 4 db 0
;       answer: times 4 db 0

SECTION .bss

        name:   resd    20
;       number: resb    5
        answer: resb    5       


SECTION .text
        extern printf
        extern scanf

    global main 
    main:
        ;set up stack frame
                push EBP       
                mov EBP, ESP   
                pushad       

        ;ask user name
                push askName     
                call printf     
                add  ESP, 8

        ; get name input
                push name       
                push formats    ; %s (string) and newline     
                call scanf
                add ESP, 8

            ;ask user number
                push askNum     
                call printf   
                add ESP, 4

            ; get usr number
                push number
                push formatd    ; %d and line feed
                call scanf     
                add ESP, 8     

            ; add number to 5555 and print mess to usr
               mov EAX, [number+5555]
               mov [answer], EAX
               push fResult    ; final sentence
               push formatsnlf
               push formatd
               call printf
               add ESP, 12

        ; destroy stack frame
                popad   
                mov ESP, EBP
                pop EBP

                ret

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: nasm problems calling C functions - printf and scanf
« Reply #1 on: November 10, 2013, 08:45:04 PM »
Well, I think you were okay up to here...
Code: [Select]
            ; add number to 5555 and print mess to usr
               mov EAX, [number+5555]
               mov [answer], EAX
               push fResult    ; final sentence
               push formatsnlf
               push formatd
               call printf
               add ESP, 12

"mov eax, [number + 5555]" is going to try to load a dword from memory at an address 5555 bytes beyond "number". You'll need to just "mov eax, [number]" and then "add eax, 5555" as a separate operation. Then... without pushing eax or the name, you push "fResult", a format string with tokens for both the name and the (new) number... and two more format strings. I'm pretty sure one format string per printf is the limit. I think you want to:
Code: [Select]
push eax ; or "push dword [answer]"
push name
push fResult
call printf
add esp, 12

That's untested.

Best,
Frank


Offline 0xFF

  • Jr. Member
  • *
  • Posts: 15
Re: nasm problems calling C functions - printf and scanf
« Reply #2 on: November 12, 2013, 02:15:07 PM »
A couple points of feedback are:

1. You're using "pushad" to save all the general purpose registers, this also saves ebp, so you could skip pushing ebp at the start, and just pushad/popad to get it back. On the other hand, this is a stand alone program, its not a procedure that'll be called by other programs or functions, so there's no reason I can see to save the registers at all. It looks like you're compiling with gcc or something, so all the prior parts of the program are doing is initialising stuff and figuring out where biits of the code will do; it's like the janitor, turning on the lights and getting out the tables and chairs for the big show, or a butler setting the table. It's a servant for the main program, it doesn't need the main program to do favours for it, keep values, it's just polite and deferential. All it wants from you is to make sure ebp is the same at the end of your program. When you ret, the butler cleans up the table, the janitor turns out the lights, it doesn't do anything functional besides tidy it all up, so no registers are really needed, except perhaps an error code (or 0 for no error) in eax if you want to be fancy. If someone's told you its 'good practice to save all registers' then they're into voodoo... its only worth it when you need to do it and thinking about whether you do or not is an important part of knowing why you're doing what you're doing.

2. It's not a big deal in a program like this which is for learning, but there are gaping security holes in the program as it stands, and it's a good thing to learn about them and spot them. You're taking input from a user and writing it to a 'buffer' with a fixed space. Most users may not have names over 20 characters in length, but I'm a nasty thinker, I'm not going to enter my name, I'm going to enter more than 20 characters and turn your program into my program, give it a whole new set of code... read up about it here: buffer overflows