在x86中调用printf来打印整数

3la*_*210 5 x86 assembly printf call nasm

我试图调用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
Run Code Online (Sandbox Code Playgroud)

此代码打印"num:1836412417"

当我尝试打印一个它有效的字符时!

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
Run Code Online (Sandbox Code Playgroud)

现在打印"num:a"

那么第一个代码出了什么问题?!!

zch*_*zch 8

db声明8位(一个字节)值,同时%d在x86上打印32位(四字节)值.

实际上,当您加载32位寄存器eaxmov eax, [an],会将字母位加载"num"到寄存器的高字节.它们在使用时会被打印为数字,使用时%d会被忽略或被忽略%c.

要声明32位值,您应该使用dd,而不是db.


lur*_*ker 5

@zch指出了这个问题。但是,如果您确实希望将字节数据项作为整数打印出来,而又不想重新定义它,那么可以这样进行:

     movsx eax, BYTE [an]       ; [an] is a byte value to be printed with %d
     push  eax
     push  dword format
     call  printf
Run Code Online (Sandbox Code Playgroud)

所述movsx指示标志上延伸的8位或16位操作数(在这种情况下,8位操作数,[an])到32位寄存器,eax。如果未签名,则可以使用movzx eax, [an](零填充)。通常在C语言中,升为整数是隐式完成的。但是在组装时,您需要自己做。