17

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」のアドレスに配置されます。

4

5 に答える 5

19

この「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

この C 関数の asm バージョンはどれですか。

#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;
}
于 2012-06-11T01:43:30.457 に答える
6

Preetに感謝します。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 
于 2013-02-24T19:45:25.347 に答える
3

これはアセンブリで検索して最初に出てくる投稿scanfなので、4年前の投稿でも正しいと思います。

Oukei さん、call scanfNASM アセンブリで次のことを行う必要があります。

  1. 外部スキャン
  2. scanf 用のフォーマットを準備する
  3. 予想される値を格納する変数または単一の変数を準備する
  4. パラメータを逆順にプッシュする
  5. scanf を呼び出す
  6. スタックを復元

だから、あなたがトレーディングしているとしましょう

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

リストに従ってください:
... 1.

section .text
extern scanf

... 2. これは Cscanfに渡す最初のパラメータで、何が得られるかを示します。1 つの整数、2 つの浮動小数点数、文字列、文字... この場合、スペースで区切られた 2 つの整数 (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

また、3 つのダブル ワード パラメータをプッシュしたため、スタック ポインタに 12 を追加する必要があることに注意してください。したがって、スタックに 12 バイト (3*4 バイト) を追加して、パラメーターを「ジャンプ」します。

※変数%dは dword を使っているのでprintf.
**,0フォーマット文字列の最後の はセンチネル文字です。

于 2016-09-18T02:33:35.930 に答える