我想创建一个打印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指令...
答案 0 :(得分:0)
" print"没有x86指令。一个值。显示输出需要特定于操作系统的接口。在"经典"在x86编程中,您可以进行BIOS调用以生成输出到屏幕。在现代保护模式操作系统中,这将不再有效。相反,您需要调用OS API函数来将输出例如显示到与您的流程关联的控制台窗口。
调用该OS API的最简单,最通用的方法是将汇编程序与C标准库链接,以便可以调用其printf
(和类似的)函数。这只需要一条CALL
指令,它将控制转移到printf
函数,执行它,并将控制权返回给代码中的以下指令。
然而,还有一个复杂因素:您必须遵循适用于您的平台和标准库函数的相应调用约定。您的问题没有提供关于您是否使用Windows,Linux或其他内容的线索。幸运的是,x86标记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
伪指令,可以自动处理为你调用函数。可能值得检查一下您选择的汇编程序是否具有类似功能。