首页 > 解决方案 > 将 nasm 与 __vectorcall 约定一起使用

问题描述

我刚刚开始使用 nasm,但我在__vectorcall约定方面遇到了一些问题。调用我的测试函数 ( sinf) 时,我从被调用者返回访问冲突。

; float sin_f(float)
global  sin_f@@4
section .text
sin_f@@4:
    push    rdi
;   sub     rsp, 16                 ; make room for xmm
    movss   [rsp - 16], xmm0        ; mov float arg onto stack
    fld     qword [rsp - 16]        ; push argument on float stack
    fsin                            ; do sin in radians
    fstp    qword [rsp - 16]        ; pop float stack
    movss   xmm0, [rsp - 16]        ; move back to xmm0
    movq    rax, xmm0
;   add     rsp, 16                 ; reset stack
    pop     rdi
    ret

我显然没有正确地进行清理,但到目前为止我所有的尝试都失败了。看着一些 MSVC dissasembly 我已经看到了他们push/pop rdi,所以我已经添加了。而不是sub/addto rsp(这导致了无人区的崩溃),我只是直接减去rsp.

本文涵盖了流行的调用约定,并提到__vectorcall类似于__fastcall. 但是,使用ret 4不会改变任何事情。另外,MSVC 本身并不这样做。哦,我也搬到了rax只是因为。

对于这些概念的任何帮助将不胜感激。谢谢!

编辑:错误是

Exception thrown at 0x00007FF6198B2C5A in demo1.exe:
0xC0000005: Access violation reading location 0x00000000B817FA20

来电反汇编:

; 13   : T sin(T angle) {

$LN3:
    movss   DWORD PTR [rsp+8], xmm0
    push    rdi
    sub rsp, 48                 ; 00000030H
    mov rdi, rsp
    mov ecx, 12
    mov eax, -858993460             ; ccccccccH
    rep stosd

; 14   :    static_assert(std::is_floating_point_v<T>, "requires floating point");
; 15   :    if constexpr (std::is_same_v<float, T>) {
; 16   :        return detail::sin_f(angle);

    movss   xmm0, DWORD PTR angle$[rsp]
    call    sin_f@@8

; 17   :    } else {
; 18   :        return detail::sin_d(angle);
; 19   :    }
; 20   : 
; 26   : }

    add rsp, 48                 ; 00000030H
    pop rdi
    ret 0

标签: assemblynasmcalling-convention

解决方案


所以主要问题是使用@@4字节大小。出于某种原因,它需要@@8。也许是因为返回值?

另外,我搞砸了 64/32 位调用。这是最终的工作版本:

; float sin_f(float)
global  sin_f@@8
section .text
sin_f@@8:
    sub     rsp, 24         ; red-zone
    movss   [rsp], xmm0     ; mov float arg onto stack
    fld     dword [rsp]     ; push argument on float stack
    fsin                            ; do sin in radians
    fstp    dword [rsp]     ; pop float stack
    movss   xmm0, [rsp]     ; move back to xmm0
    add     rsp, 24         ; red-zone
    ret

推荐阅读