web-dev-qa-db-ja.com

x86でprintfを呼び出して整数を出力する

Printfを呼び出して整数を出力しようとしていますが、正しい値が出力されません。

section .data

         an:    db 1
         format: db "num: %d" , 10, 0

section .text
         global main
         extern printf

main:
         Push ebp
         mov ebp,esp

         mov eax, [an]
         Push eax
         Push dword format
         call printf

         add esp, 8
         mov esp,ebp
         pop ebp

         mov eax, 0
         ret

このコードは「num:1836412417」を出力します

charを印刷しようとするとうまくいきます!

section .data

         an:    db 'a'
         format: db "num: %c" , 10, 0

section .text
         global main
         extern printf

main:
         Push ebp
         mov ebp,esp

         mov eax, [an]
         Push eax
         Push dword format
         call printf

         add esp, 8
         mov esp,ebp
         pop ebp

         mov eax, 0
         ret

現在は「num:a」と出力されます

最初のコードの何が問題になっていますか?!!

6
3la210

dbは8ビット(1バイト)の値を宣言し、%dはx86で32ビット(4バイト)の値を出力します。

実際、32ビットレジスタeaxmov eax, [an]とともにロードすると、文字のビット"num"がレジスタの上位バイトにロードされます。 %dを使用する場合は、後で数値として出力されるか、%cを使用する場合は無視されます。

32ビット値を宣言するには、ddではなくdbを使用する必要があります。

8
zch

@zchが問題を指摘しました。しかし、本当にバイトデータ項目を整数として出力する必要があり、それを再定義する余裕がない場合は、次の方法で行うことができます。

     movsx eax, BYTE [an]       ; [an] is a byte value to be printed with %d
     Push  eax
     Push  dword format
     call  printf

movsx命令符号は、8ビットまたは16ビットのオペランド(この場合、8ビットのオペランド[an])を32ビットのレジスタeaxに拡張します。署名されていない場合は、movzx eax, [an](ゼロフィル)を使用します。通常Cでは、整数への昇格は暗黙的に行われます。しかし、アセンブリでは、自分で行う必要があります。

5
lurker