可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I can't figure this out. I'm obviously really new to Assembly, and I'm trying to figure out how to use Scanf to get user input.
I know to use Printf all I have to do is push the data I want to write on the screen into the stack like this:
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
But I can't figure out how to use Scanf. Can someone please just give me the simplest possible source code you can for Scanf? I really just want to put what the user types in.
I'm not used to 32bit Assembly. I've only ever used 16bit, and I know in 16bit (DOS) you can just do this:
mov ah, 3fh
mov dx, input
int 21h
input rb 100d
And whatever you type in will the placed at the address of "input."
Please bear with me. I'm trying to figure this out.
回答1:
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;
}
回答2:
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
回答3:
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:
- Extern scanf
- Prepare a formatation for you scanf
- Prepare the variables or single variable to store the values expected
- Push the parameters in backward order
- Call scanf
- 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.
回答4:
Lets say you want to do something like
scanf("%d %d", &var1, &var2);
That takes two values and store them in the variables.
In assembly you would push
the addres of the variables into the stack (in backward order) and then call scanf
.
Something like you have two variables
var1 resd 1
var2 resd 1
... and then
push var2
push var1
call scanf
*Note that I pushed them in backward order, the first value will be stored in var1.
After execution the values you entered will be stored in the variables.
If you want only one value just push one variable.