返回介绍

21.4 从 32 位值转化为 64 位值

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

#!cpp
#include <stdint.h>
int64_t f7 (int64_t a, int64_t b, int32_t c)
{
        return a*b+c;
};

int64_t f7_main ()
{
        return f7(12345678901234, 23456789012345, 12345);
};

代码 21.7: MSVC 2012 /Ox /Ob1

#!bash
_a$ = 8                                 ; size = 8
_b$ = 16                                ; size = 8
_c$ = 24                                ; size = 4
_f7     PROC
        push        esi
        push        DWORD PTR _b$[esp+4]
        push        DWORD PTR _b$[esp+4]
        push        DWORD PTR _a$[esp+12]
        push        DWORD PTR _a$[esp+12]
        call        __allmul ; long long multiplication
        mov         ecx, eax
        mov         eax, DWORD PTR _c$[esp]
        mov         esi, edx
        cdq                 ; input: 32-bit value in EAX; output: 64-bit value in EDX:EAX
        add         eax, ecx
        adc         edx, esi
        pop         esi
        ret         0
_f7     ENDP

_f7_main PROC
        push        12345               ; 00003039H
        push        5461                ; 00001555H
        push        1972608889          ; 75939f79H
        push        2874                ; 00000b3aH
        push        1942892530          ; 73ce2ff2H
        call        _f7
        add     esp, 20                 ; 00000014H
        ret     0
_f7_main ENDP

这里我们有必要将有符号的 32 位值从 c 转化为有符号的 64 位值。无符号值的转化简单了当:所有的高位部分全部置 0。但是这样不适合有符号的数据类型:符号标志应复制到结果中的高位部分。这里用到的指令是 CDQ,它从 EAX 中取出数值,将其变为 64 位并存放到 EDX:EAX 这一对寄存器中。换句话说,指令 CDQ 从 EAX 中获取符号(通过 EAX 中最重要的位),并根据它来设置 EDX 中所有位为 0 还是为 1。它的操作类似于指令 MOVSX(13.1.1)。

代码 21.8: GCC 4.8.1 -O3 -fno-inline

#!bash
_f7:
        push        edi
        push        esi
        push        ebx
        mov         esi, DWORD PTR [esp+16]
        mov         edi, DWORD PTR [esp+24]
        mov         ebx, DWORD PTR [esp+20]
        mov         ecx, DWORD PTR [esp+28]
        mov         eax, esi
        mul         edi
        imul        ebx, edi
        imul        ecx, esi
        mov         esi, edx
        add         ecx, ebx
        mov         ebx, eax
        mov         eax, DWORD PTR [esp+32]
        add         esi, ecx
        cdq             ; input: 32-bit value in EAX; output: 64-bit value in EDX:EAX
        add         eax, ebx
        adc         edx, esi
        pop         ebx
        pop         esi
        pop         edi
        ret
_f7_main:
        sub         esp, 28
        mov         DWORD PTR [esp+16], 12345               ; 00003039H
        mov         DWORD PTR [esp+8], 1972608889           ; 75939f79H
        mov         DWORD PTR [esp+12], 5461                ; 00001555H
        mov         DWORD PTR [esp], 1942892530             ; 73ce2ff2H
        mov         DWORD PTR [esp+4], 2874                 ; 00000b3aH
        call
_f7
        add         esp, 28
        ret

GCC 生成的汇编代码跟 MSVC 一样,但是在函数中内联乘法代码。 更多:32 位值在 16 位环境中(30.4)

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

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

发布评论

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