How to use scanf in NASM?

Thanks Preet. I made a simple example based on your code to illustrate the use of scanf.

Program that requests an integer and prints it out to the screen:

section .text
  global main
  extern printf
  extern scanf

section .data
  message: db "The result is = %d", 10, 0
  request: db "Enter the number: ", 0
  integer1: times 4 db 0 ; 32-bits integer = 4 bytes
  formatin: db "%d", 0

main:
  ;  Ask for an integer
  push request
  call printf
  add esp, 4    ; remove the parameter

  push integer1 ; address of integer1, where the input is going to be stored (second parameter)
  push formatin ; arguments are right to left (first  parameter)
  call scanf
  add esp, 8    ; remove the parameters

  ; Move the value under the address integer1 to EAX
  mov eax, [integer1]

  ; Print out the content of eax register
  push eax
  push message
  call printf
  add esp, 8

  ;  Linux terminate the app
  MOV AL, 1
  MOV EBX, 0 
  INT 80h 

This is the first post that shows up when you search for scanf in assembly, so, even if its a 4 years old post, I think it should be correct.

Oukei, so, to call scanf in NASM assembly you need to:

  1. Extern scanf
  2. Prepare a formatation for you scanf
  3. Prepare the variables or single variable to store the values expected
  4. Push the parameters in backward order
  5. Call scanf
  6. Restore stack

So, lets say you're traying to

scanf ("%d %d", &val1, &val2);

and following the list:
... 1.

section .text
extern scanf

... 2. This is the first parameter you pass to your C scanf, it says what will you get. One integer, two, a float, string, char... In this case, two integers separated by a space (also works with Enter)

section .data
fmt: db "%d %d",0

... 3.

section .bss
val1: resd 1
val2: resd 1

... 4 5 6. Note that you push the address of the variables, not its content (i.e. [var])

push val2
push val1
push fmt
call scanf
add esp, 12

Also note that you have to add 12 to the stack pointer because you pushed 3 double word parameters. So you add 12 bytes (3*4 bytes) to the stack to "jump" the parameters.

*I declared dword for the variables because %d uses dword, just as printf.
**The ,0 in the end of the formatation string is a sentinel character.


I found this 'Programming in NASM.PDF'

; add1.asm
SECTION .data
    message1: db "Enter the first number: ", 0
    message2: db "Enter the second number: ", 0
    formatin: db "%d", 0
    formatout: db "%d", 10, 0 ; newline, nul terminator
    integer1: times 4 db 0 ; 32-bits integer = 4 bytes
    integer2: times 4 db 0 ;
SECTION .text
   global _main 
   extern _scanf 
   extern _printf     

_main:

   push ebx ; save registers
   push ecx
   push message1
   call printf

   add esp, 4 ; remove parameters
   push integer1 ; address of integer1 (second parameter)
   push formatin ; arguments are right to left (first parameter)
   call scanf

   add esp, 8 ; remove parameters
   push message2
   call printf

   add esp, 4 ; remove parameters
   push integer2 ; address of integer2
   push formatin ; arguments are right to left
   call scanf

   add esp, 8 ; remove parameters

   mov ebx, dword [integer1]
   mov ecx, dword [integer2]
   add ebx, ecx ; add the values          ; the addition
   push ebx
   push formatout
   call printf                            ; call printf to display the sum
   add esp, 8                             ; remove parameters
   pop ecx
   pop ebx ; restore registers in reverse order
   mov eax, 0 ; no error
   ret

Which is the asm version of this C function:

#include <stdio.h>
int main(int argc, char *argv[])
{
    int integer1, integer2;
    printf("Enter the first number: ");
    scanf("%d", &integer1);
    printf("Enter the second number: ");
    scanf("%d", &integer2);
    printf("%d\n", integer1+integer2);
    return 0;
}

Tags:

Assembly

Nasm