返回介绍

15.2 通过参数通过浮点数

发布于 2025-02-22 14:00:45 字数 3242 浏览 0 评论 0 收藏 0

#!bash
#include <math.h>
#include <stdio.h>
int main ()
{
    printf ("32.01 ^ 1.54 = %lf
", pow (32.01,1.54));
    return 0;
}

15.2.1 x86

让我们来看看在(msvc2010)中得到的东西

清单 15.3 :MSVC 2010

#!bash
CONST   SEGMENT
__real@40400147ae147ae1 DQ 040400147ae147ae1r   ; 32.01
__real@3ff8a3d70a3d70a4 DQ 03ff8a3d70a3d70a4r   ; 1.54
CONST ENDS

_main     PROC
        push    ebp
        mov     ebp, esp
        sub     esp, 8 ; allocate place for the first variable
        fld     QWORD PTR __real@3ff8a3d70a3d70a4
        fstp    QWORD PTR [esp]
        sub     esp, 8 ; allocate place for the second variable
        fld     QWORD PTR __real@40400147ae147ae1
        fstp    QWORD PTR [esp]
        call    _pow
        add     esp, 8 ; "return back" place of one variable.

; in local stack here 8 bytes still reserved for us.
; result now in ST(0)

        fstp    QWORD PTR [esp] ; move result from ST(0) to local stack for printf()
        push    OFFSET $SG2651
        call    _printf
        add     esp, 12
        xor     eax, eax
        pop     ebp
        ret     0
_main       ENDP

FLD 和 FSTP 读取 FPU 的栈中的变量。pow()从 FPU 栈中拿出两个值然后将结果返回到 ST(0) 寄存器中。printf()函数从本地栈中取出 8 字节并且将他们翻译为双精度变量。

15.2.2 ARM+Non-optimizing Xcode(LLVM)+thumb-2 模式

#!bash
_main
var_C       = -0xC
            PUSH    {R7,LR}
            MOV     R7, SP
            SUB     SP, SP, #4
            VLDR    D16, =32.01
            VMOV    R0, R1, D16
            VLDR    D16, =1.54
            VMOV    R2, R3, D16
            BLX     _pow
            VMOV    D16, R0, R1
            MOV     R0, 0xFC1 ; "32.01 ^ 1.54 = %lf
"
            ADD     R0, PC
            VMOV    R1, R2, D16
            BLX     _printf
            MOVS    R1, 0
            STR     R0, [SP,#0xC+var_C]
            MOV     R0, R1
            ADD     SP, SP, #4
            POP     {R7,PC}
dbl_2F90    DCFD 32.01      ; DATA XREF: _main+6
dbl_2F98    DCFD 1.54       ; DATA XREF: _main+E

就像我以前写的一样,64 位的浮点数是成对传递给 R 系列寄存器的。这样的代码是冗陈的(当然是因为优化选项关掉了),因为,事实上直接从 R 系列寄存器传递值,不借助 D 系列寄存器是可能的。

因此我们可以看到,_pow 将第一个参数放入 R0 和 R1 中,第二个参数放入 R2 和 R3 中。函数结果放入 R0 和 R1 中。_pwn 的结果先放入了 D16 中,然后再放入 R1 和 R2 中,然后 printf 函数将取走这个值。

15.2.3 ARM+非优化模式 keil+ARM 模式

#!bash
_main
                STMFD   SP!, {R4-R6,LR}
                LDR     R2, =0xA3D70A4 ; y
                LDR     R3, =0x3FF8A3D7
                LDR     R0, =0xAE147AE1 ; x
                LDR     R1, =0x40400147
                BL      pow
                MOV     R4, R0
                MOV     R2, R4
                MOV     R3, R1
                ADR     R0, a32_011_54Lf ; "32.01 ^ 1.54 = %lf
"
                BL      __2printf
                MOV     R0, #0
                LDMFD   SP!, {R4-R6,PC}

y               DCD 0xA3D70A4       ; DATA XREF: _main+4
dword_520       DCD 0x3FF8A3D7      ; DATA XREF: _main+8
; double x
x               DCD 0xAE147AE1      ; DATA XREF: _main+C
dword_528       DCD 0x40400147      ; DATA XREF: _main+10
a32_011_54Lf    DCB "32.01 ^ 1.54 = %lf",0xA,0
                                    ; DATA XREF: _main+24

D 系列寄存器在这里不使用,只成对地使用 R 系列的寄存器

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文