Как использовать 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".
Пожалуйста, несите меня. Я пытаюсь понять это.
Ответы
Ответ 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.
После выполнения введенные значения будут сохранены в переменных.
Если вы хотите только одно значение, просто нажмите одну переменную.