Подтвердить что ты не робот

Как использовать Scanf в NASM?

Я не могу понять это. Я, очевидно, очень новичок в Assembly, и я пытаюсь выяснить, как использовать Scanf для ввода данных пользователя.

Я знаю, что использовать Printf все, что мне нужно сделать, это нажать на данные, которые я хочу записать на экране, в стек:

global _main
extern _printf
extern _scanf

section .data
msg db "Hi", 0

section .text
_main:
  push ebp
  mov ebp, esp  

  push msg
  call _printf

  mov esp, ebp
  pop ebp
ret

Но я не могу понять, как использовать Scanf. Может кто-нибудь, пожалуйста, просто дайте мне самый простой возможный исходный код для Scanf? Я просто хочу указать, что пользователь вводит.

Я не привык к 32-битной сборке. Я только когда-либо использовал 16 бит, и я знаю, что в 16 бит (DOS) вы можете просто сделать это:

mov ah, 3fh
mov dx, input
int 21h

input rb 100d

И все, что вы введете, будет помещено по адресу "input".

Пожалуйста, несите меня. Я пытаюсь понять это.

4b9b3361

Ответ 1

Я нашел это 'Программирование в 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

Какова версия asm этой функции C:

#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;
}

Ответ 2

Спасибо. Я сделал простой пример, основанный на вашем коде, чтобы проиллюстрировать использование scanf.

Программа, которая запрашивает целое число и выводит его на экран:

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 

Ответ 3

Это первое сообщение, которое появляется при поиске scanf в сборке, поэтому, даже если это 4-летняя почта, я думаю, что это должно быть правильно.

Oukei, поэтому для call scanf в сборке NASM вам необходимо:

  • Extern scanf
  • Подготовьте форматирование для scanf
  • Подготовьте переменные или одну переменную для хранения ожидаемых значений
  • Нажмите параметры в обратном порядке
  • Вызов scanf
  • Восстановить стек

Итак, скажем, вы тянете к

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

и следуя за списком:
... 1.

section .text
extern scanf

... 2. Это первый параметр, который вы передаете на свой C scanf, он говорит, что вы получите. Одно целое, два, float, string, char... В этом случае два целых числа, разделенные пробелом (также работает с Enter)

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

... 3.

section .bss
val1: resd 1
val2: resd 1

... 4 5 6. Обратите внимание, что вы нажимаете адрес переменных, а не его содержимое (т.е. [Var])

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

Также обратите внимание, что вы должны добавить 12 к указателю стека, потому что вы нажали 3 параметра двойного слова. Таким образом, вы добавляете 12 байт (3 * 4 байта) в стек, чтобы "перескакивать" параметры.

* Я объявил dword для переменных, потому что %d использует dword, так же, как printf.
** ,0 в конце строки форматирования является часовым символом.

Ответ 4

Предположим, вы хотите сделать что-то вроде

scanf("%d %d", &var1, &var2);

Это принимает два значения и сохраняет их в переменных.

В сборке вы бы push добавляли переменные в стек (в обратном порядке), а затем call scanf.

Что-то вроде двух переменных

var1 resd 1
var2 resd 1

... и затем

push var2
push var1
call scanf

* Обратите внимание, что я нажал их в обратном порядке, первое значение будет сохранено в var1.

После выполнения введенные значения будут сохранены в переменных.

Если вы хотите только одно значение, просто нажмите одну переменную.