2012-06-11 15 views
13

No puedo resolver esto. Obviamente soy realmente nuevo en Assembly, y estoy tratando de descubrir cómo usar Scanf para obtener la entrada del usuario.Cómo usar Scanf en NASM?

sé utilizar Printf todo lo que tengo que hacer es empujar a los datos que yo quiero escribir en la pantalla en la pila de la siguiente manera:

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 

pero no puedo encontrar la manera de utilizar Scanf. ¿Alguien puede darme el código fuente más simple posible para Scanf? Realmente solo quiero poner lo que escribe el usuario.

No estoy acostumbrado a 32bit Assembly. He usado solamente siempre 16 bits, y sé que en 16 bits (DOS) sólo se puede hacer esto: "entrada"

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

input rb 100d 

Y todo lo que teclee el colocado en la dirección de

Por favor tengan paciencia conmigo. Estoy tratando de resolver esto.

Respuesta

15

yo encontramos este '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 

que es la versión de esta función 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; 
} 
+0

Hmm, gracias, esto ayuda. También veré ese PDF. – user1432532

+0

¿Dónde está el código de ensamblaje para printf (instrucción "% d \ n", integer1 + integer2)? – azurkin

+0

@azurkin - Bien manchado. Está en el PDF y lo he agregado –

3

Gracias Preet. Hice un ejemplo simple basado en su código para ilustrar el uso de scanf.

programa que solicita un entero y lo imprime en la pantalla:

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 
0

digamos que usted quiere hacer algo como

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

que toma dos valores y almacenarlos en las variables.

En el ensamblaje, se push las direcciones de las variables en la pila (en orden inverso) y luego call scanf.

Algo como que tiene dos variables

... y luego

push var2 
push var1 
call scanf 

* Tenga en cuenta que los empujó hacia atrás con el fin, el primer valor se almacenará en var1.

Después de la ejecución, los valores que ingresó se almacenarán en las variables.

Si solo desea un valor, simplemente presione una variable.

+0

No olvides abrir la pila después de que el escaneo vuelva. ('add esp, 8' para el código de 32 bits, o' add rsp, 16' para el de 64 bits). –

1

Esta es la primera publicación que aparece cuando busca scanf en ensamblaje, por lo tanto, incluso si es una publicación de 4 años, creo que debería ser correcta.

Oukei, por lo que, a call scanf en el montaje NASM necesita:

  1. scanf Externo
  2. Preparar una formatation para usted Scanf
  3. Preparar las variables o variable individual para almacenar los valores esperados
  4. Empuje los parámetros en orden inverso
  5. Llamada scanf
  6. Pila de restauración

Por lo tanto, digamos que usted está traying a

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

y siguiendo la lista:
... 1.

section .text 
extern scanf 

... 2. Este es el primer parámetro que pasa a su C scanf, dice qué obtendrá. Un número entero, dos, un flotador, cadena, char ... En este caso, dos enteros separados por un espacio (también funciona con Enter)

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

... 3.

section .bss 
val1: resd 1 
val2: resd 1 

... 4 5 6. Observe que se presiona la dirección de las variables, no su contenido (es decir, [var])

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

también tenga en cuenta que hay que añadir 12 al puntero de pila, ya que empujó 3 doble wo parámetros rd. Entonces agrega 12 bytes (3 * 4 bytes) a la pila para "saltar" los parámetros.

* He declarado dword para las variables porque %d usa dword, igual que printf.
** El ,0 al final de la cadena de formatación es un personaje centinela.

+0

Puede fusionar sus cuentas (busque en [meta] para averiguar cómo). O bien, puede eliminar su respuesta anterior de su otra cuenta, ya que de todos modos no tiene ningún voto positivo. Y por favor [editar] este para que soporte por sí mismo, en lugar de hacer referencia a su otra publicación. –

+0

Respondí como invitado con el nombre de PunditPoe, no puedo determinar si puedo "ingresar" esta cuenta de invitado y eliminar la publicación. Pero, de todos modos, corregí este para sostenerme solo. Gracias. –