打印存储在eax:ebx x86中的qword

时间:2016-12-13 18:32:47

标签: assembly x86

我想创建一个打印qword(十进制)的宏。

show_qd macro nr
   lea edx,[nr]
   mov eax,[edx] ;upper 32 bits
   mov ebx,[edx+4] ;lower 32 bits

   ;print code here;

endm

可悲的是,我无法弄清楚如何使用x86指令...

1 个答案:

答案 0 :(得分:0)

" print"没有x86指令。一个值。显示输出需要特定于操作系统的接口。在"经典"在x86编程中,您可以进行BIOS调用以生成输出到屏幕。在现代保护模式操作系统中,这将不再有效。相反,您需要调用OS API函数来将输出例如显示到与您的流程关联的控制台窗口。

调用该OS API的最简单,最通用的方法是将汇编程序与C标准库链接,以便可以调用其printf(和类似的)函数。这只需要一条CALL指令,它将控制转移到printf函数,执行它,并将控制权返回给代码中的以下指令。

然而,还有一个复杂因素:您必须遵循适用于您的平台和标准库函数的相应调用约定。您的问题没有提供关于您是否使用Windows,Linux或其他内容的线索。幸运的是,标记wiki中提供了有关x86调用约定的详细信息,可访问here。通常,32位调用约定将从右到左传递堆栈上的参数。并且C标准库函数实际上总是调用者清理(即使在Windows上,其中常见的是被调用者清理约定),因此您负责在打电话后清理堆栈。

因此,就像演示一样,这里是你如何调用printf来打印存储在EAX寄存器中的32位整数:

push  eax                  ; push 32-bit integer value from EAX onto stack
push  OFFSET strFormat     ; push pointer to format string onto stack
call  printf
add   esp, 8               ; clean up stack

strFormat必须是存储在可执行文件DATA部分中的字符串。格式字符串与C相同,因为它的功能完全相同。在这种情况下,它会将指针推送到包含"%d"的字符串。

除了格式字符串为"%lld"之外,打印64位值的情况大致相同(使用C中的long long类型,x86-32为64位)。您需要遵循调用约定的规则,将64位整数参数传递给函数。这可能只是将两个32位半部分推入堆栈。假设64位值在EDX:EAX中规范地存储,代码如下:

push  edx                    ; push upper 32 bits of 64-bit integer value onto stack
push  eax                    ; push lower 32 bits of 64-bit integer value onto stack
push  OFFSET strFormat64     ; push pointer to format string onto stack
call  printf
add   esp, 12                ; clean up stack

如果值在内存中,那么您可以使用问题中显示的代码:

lea   edx, DWORD PTR [value]
mov   eax, DWORD PTR [edx]
mov   edx, DWORD PTR [edx+4]

push  edx
push  eax
push  OFFSET strFormat64
call  printf

add   esp, 12

请注意,如果将其实现为宏,则会破坏寄存器。确保这是明确记录的,或者保存并恢复宏内部的寄存器 - 否则,当您在代码中使用它时,最终会遇到难以调试的问题!而且,根据您的调用约定,您可能需要确保堆栈已正确对齐,这在宏中很难干净利落地完成。 MASM有一个INVOKE伪指令,可以自动处理为你调用函数。可能值得检查一下您选择的汇编程序是否具有类似功能。