【问题标题】:Windows ASM printf with float带有浮点数的 Windows ASM printf
【发布时间】:2016-06-26 21:34:04
【问题描述】:

我一直在尝试在汇编程序中与 Windows 中的标准 C 库进行交互,但遇到了麻烦。由于某种原因,我无法让 printf 接受浮点变量,所以这里出了点问题。

这是我可以创建的最短的程序来演示该问题。我已经包含了解释我对应该发生的事情的理解的 cmets。

谢谢

;
; Hello64.asm
; A simple program to print a floating point number in windows
;
; assemble: nasm float64.asm -f win64
; link: golink /console /entry main float64.obj MSVCRT.dll
;

; tell assembler to generate 64-bit code
;
bits 64

; data segment
section .data use64

pi  dq 3.14159

textformat: db "hello, %lf!",0x0a, 0x00     ; friendly greeting

; set up the .text segment for the code
section .text use64

; global main is the entry point
global main
; note that there is no _ before printf here, unlike in OS X
extern printf

main:
mov rcx, textformat 
movq xmm0, qword [pi]
mov rax, 1      ; need to tell printf how many floats
call printf

; note next step - this puts a zero in rax
xor rax,rax
ret ; this returns to the OS based on how Windows calls programs.
; this return causes a delay then the program exits.

【问题讨论】:

  • 原谅我的无知,但是osx和这有什么关系?
  • 对不起-该评论是给我的。在带有 NASM 的 OS X 中,您需要在 clib 函数名称的名称前放置一个 _,以便链接器正确链接它们。
  • 我很确定 printf 要求运行时已初始化,而您没有这样做。
  • @RaymondChen,你将如何初始化运行时? Jester 提供的代码按照编写的方式工作,我已经用文本完成了“hello world”,没有任何额外的步骤来初始化运行时。
  • 哦,是的,很好看,@Raymond。他的链接器命令将入口点设置为main,而不是让CRT 启动代码调用main。在 Linux 上,如果您想编写“裸”可执行文件,只需编写 _start 而不是 main。即使没有 crt 启动代码,glibc 之类的 printf 和 malloc 也可以工作,至少在我完成的少量测试中是这样。

标签: windows assembly nasm x86-64 calling-convention


【解决方案1】:

您设法混合了 microsoft 和 sysv 约定。正确的做法是:

mov rcx, textformat 
movq xmm1, qword [pi]
movq rdx, xmm1  ; duplicate into the integer register
sub rsp, 40     ; allocate shadow space and alignment (32+8)
call printf
add rsp, 40     ; restore stack
xor eax, eax
ret

根据MSDN,使用可变参数时:

仅对于浮点值,整数和浮点寄存器都将包含浮点值,以防被调用者期望整数寄存器中的值。

【讨论】:

  • 做到了!我不知道您必须将其复制到相应的常规寄存器中(按参数传递顺序)。另外,为什么堆栈对齐是 40?我理解四个标准参数的“home”空间的 32,但是为什么要额外增加 8 个字节(64 位)?
  • 嗯,这是一个奇怪的 ABI 设计。我不知道 Windows 调用约定是这样做的。 @querist:只有varargs functions that need float args duplicated in the corresponding integer reg。额外的 8B 是这样在 call 推送返回地址后堆栈将 16B 对齐。
  • 谢谢,@PeterCordes。
  • @PeterCordes 这样被调用的函数可以很容易地溢出它的参数。
  • @PeterCordes 抱歉,我在回答“为什么浮点可变参数复制到整数寄存器中?”的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
相关资源
最近更新 更多