代码之家  ›  专栏  ›  技术社区  ›  scx

将NASM与vectorcall约定结合使用

  •  0
  • scx  · 技术社区  · 8 年前

    我刚开始使用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的不安定我见过他们 push/pop rdi ,所以我加了一句。而不是 sub/add 到 rsp (在无人区内造成撞车)我只是直接退步 相对标准偏差 .

    这个 article 包括流行的呼叫约定,并提到 _矢量呼叫 类似于 __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
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   scx    8 年前

    所以主要的问题是使用 @@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
    
    推荐文章