【问题标题】:AT&T assembly: how to mult a double by 2 without local variable. Shift Double?AT&T 汇编:如何在没有局部变量的情况下将双倍乘以 2。换双?
【发布时间】:2014-06-19 08:06:57
【问题描述】:

[作业]:尝试完全按照 C 代码所说的去做。
C版完整功能代码注释:

/*
double f(double x) 
{
    return x * 2.0;
}

double foo (int a[], double b[], int n) 
{
    int *pint;
    double *pdouble;

double sum = 0.0;

for (pint = a, pdouble = b; n-- ; pint++, pdouble++) 
{
    *pdouble = f((double)*pint);
    sum += *pdouble;
}

return sum;
}
*/

.text

.globl f
f:
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ebx

/*fldl  8(%ebp)
fstpl   8(%ebp)*/
/*movl  8(%ebp), %ebx*/
shll    $2, 8(%ebp)
fldl    8(%ebp)

popl    %ebx
movl    %ebp, %esp
popl    %ebp
ret

.globl foo
foo:    
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ebx
    pushl   %esi


subl    $16, %esp   /* for the local variables          */

fldz            /* 0 to the top of the FPU's stack      */
fstpl   (%esp)      /* double sum = 0               */

movl    8(%ebp), %ebx   /* > pint                   */
movl    %ebx, -4(%ebp)  /*           = a <  | INIT          */
movl    12(%ebp), %esi  /* > pdouble                    */
movl    %esi, -8(%ebp)  /*       = b <      | INIT          */
L1: cmpl    $0, 16(%ebp)
js  outfor


pushl   %eax
pushl   %ecx
pushl   %edx

movl    -4(%ebp), %edi  
fildl   (%edi)      /* *pint to the top of FPU'S stack      */
subl    $8, %esp    /* > pushdouble                 */
fstpl   (%esp)      /*              *pint <             */
call    f       /* f((double)*pint) to the top of FPU'S stack   */
addl    $8, %esp    /* clears double pint from stack        */

popl    %edx
popl    %ecx
popl    %eax


movl    -8(%ebp), %eax
fldl    (%eax)      /* *pdouble to the top of FPU's stack       */ 

faddl   -16(%ebp)   /* sum += *pdouble (stored in FPU'S stack)  */
fstpl   -16(%ebp)   /* sum += *pdouble (stored in sum)      */

decl    16(%ebp)

addl    $4, -4(%ebp)
addl    $8, -8(%ebp)
jmp     L1

outfor: fldl    -16(%ebp)

popl    %esi
popl    %ebx
movl    %ebp, %esp
popl    %ebp

foo 将同时调用f。我的问题就在那里。我如何告诉编译器以double 威胁x?我最好的选择fldl 8(%ebp) fstpl 8(%ebp) 是给我糟糕的数字。显然,任何其他后缀 l 的指令都将其威胁为 4 字节长。

然后,一旦我对x 进行了正确解释,如何在不使用局部变量的情况下将 if 乘以 2.0(读得好,不是整数)?我尝试使用shll,但似乎不存在double 值的转变。我也不能fldl $2

【问题讨论】:

  • 要乘以 2,您可以将值添加到自身。
  • 这么想,但根本不会是双倍的,对不起小姐,这是一个家庭作业。
  • fld1 也是如此,将其添加到自身并将结果乘以参数。
  • 起初我以为你在做一些基于体积的计算! pintpdouble 不是很有帮助的名字。
  • 假设我必须将它乘以 50.0 或 500.0 或 65363.0,那会怎样?仍然需要正确的xanyways。

标签: c assembly double bit-shift att


【解决方案1】:

您不能将 double 左移以将其乘以 2,但您可以将 double 视为 64 位整数并递增指数字段(溢出可能是一个问题)。目前尚不清楚没有局部变量是什么意思。在 X86 汇编中,您可以使用 add immediate to memory 来增加指数字段,但该函数返回一个可以被视为局部变量的值。

【讨论】:

  • 据我所知,使用 -X(%ebp) 地址的任何东西都是局部变量@rcgldr
【解决方案2】:

双浮点数在其位中有几个不同的信息。因此,不能只是将其转移以使其翻倍。如前所述,您可以自行添加它。浮点值将在 FPU 寄存器ST0 中返回(cdecl 调用约定)。看看下面的程序:

# Name:     double_the_double.s
# Compile:  gcc -m32 double_the_double.s
# Run:      ./a.out

.globl main

.section .data
    dubbel: .double 50.0
    result: .double 0.0
    fmt: .asciz "%f\n"

.section .text

f:
    fldl 4(%esp)
    fadd %st(0),%st(0)
    ret

main:

    pushl (dubbel+4)
    pushl (dubbel)
    push $fmt
    call printf
    add $12, %esp

    pushl (dubbel+4)
    pushl (dubbel)
    call f
    add $8, %esp
    fstpl (result)

    pushl (result+4)
    pushl (result)
    push $fmt
    call printf
    add $12, %esp

    # Exit from _main
    ret

【讨论】:

    【解决方案3】:

    我看到您的 *pint 是一个整数,因此您可以使用 shl $1, %reg 乘以 2(而不是 shl $2, %reg 乘以 4。)

    如果你想将一个 double 乘以 2,你应该将它添加到自身。可能是最好/最快的处理方式。

    如果您真的想手动执行此操作,您需要找到双精度的定义、它的符号、它的指数和它的尾数。乘以 2 表示指数加 1:

    +----+-----------+-----------+
    | 63 | 62 ... 52 | 51 ... 00 |
    +----+-----------+-----------+
    |  X | x x x x x | x x x x x |
    +----+-----------+-----------+
    

    (Read more about IEEE floating point formats)

    因为有这个标志,最简单的可能是这样的:

    mov (%r1), %r2         ; Load the double
    roll $1, %r2           ; move the sign out of the way (bit 0)
    mov $(1 << 53), %r3    ; add 1 to exponent (shifted by 1 to the left)
    add %r3, %r2           ; do the add now
    rolr $1, %r2           ; restore the sign in bit 63
    

    但是,这并不能解决溢出问题......而且它可能比使用 FPU 将双精度数添加到自身要慢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多