2011-11-15 97 views
1

基本上,我所要做的就是使用汇编中的浮点运算将矩阵乘以一个向量。看起来是这样的AT&T语法中的浮点运算

我的第一稿:

.data 
    mat: .float 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 
    vek: .float 1.0, 2.0, 3.0 
    res: .float 0.0, 0.0 
    .text 
    .globl main 
    main: 
    ; here goes the magic 
    call exit 

不幸的是,我已经试过不起作用。我知道如何做基本的算术运算(比如faddp,fmulp等),但是我仍然无法有效地存储它。 fstpl似乎并没有工作。

任何人都可以给我一个粗略的草图(不是如何使这个矩阵 - 向量乘法)如何使用FPU命令以及如何将计算结果存储在寄存器中?

由于提前,

+2

是否有某些原因需要使用(传统)'x87'指令? SSE更容易使用。 –

回答

2

在C第一次实现,测试,然后使用gcc -S生成汇编源程序,然后要么使用原样或使用它作为你自己的代码模板。

E.g.这里是一个C代码实现,mat_vec.c

#include <stdio.h> 

int main(void) 
{ 
    // note: use "volatile" qualifier for input data otherwise gcc will 
    //  just optimise all the arithmetic away... 
    volatile float mat[2][3] = { { 1.0f, 2.0f, 3.0f }, { 4.0f, 5.0f, 6.0f } }; 
    volatile float vek[3] = { 1.0f, 2.0f, 3.0f }; 
    float res[2] = { 0.0f, 0.0f }; 

    res[0] = mat[0][0] * vek[0] + mat[0][1] * vek[1] + mat[0][2] * vek[2]; 
    res[1] = mat[1][0] * vek[0] + mat[1][1] * vek[1] + mat[1][2] * vek[2]; 

    printf("res = { %g, %g }\n", res[0], res[1]); 

    return 0; 
} 

让我们确保它的工作原理:

$ gcc -Wall -Os -m32 -march=i686 mat_vec.c -o mat_vec 
$ ./mat_vec 
res = { 14, 32 } 
$ 

看起来不错,所以让我们产生汇编源:

$ gcc -Wall -Os -m32 -march=i686 -S mat_vec.c -o mat_vec.S 
$ cat mat_vec.S 
    .cstring 
LC6: 
    .ascii "res = { %g, %g }\12\0" 
    .text 
.globl _main 
_main: 
    pushl %ebp 
    movl $0x40000000, %ecx 
    movl %esp, %ebp 
    movl $0x40400000, %edx 
    pushl %esi 
    movl $0x40800000, %eax 
    pushl %ebx 
    movl $0x3f800000, %esi 
    subl $96, %esp 
    movl %esi, -44(%ebp) 
    movl %ecx, -40(%ebp) 
    movl %edx, -36(%ebp) 
    movl %eax, -32(%ebp) 
    movl $0x40a00000, %eax 
    movl %eax, -28(%ebp) 
    movl $0x40c00000, %eax 
    movl %eax, -24(%ebp) 
    movl %esi, -20(%ebp) 
    movl %ecx, -16(%ebp) 
    movl %edx, -12(%ebp) 
    flds -44(%ebp) 
    flds -20(%ebp) 
    fstps -72(%ebp) 
    flds -40(%ebp) 
    flds -16(%ebp) 
    fstps -68(%ebp) 
    flds -36(%ebp) 
    fstps -64(%ebp) 
    flds -12(%ebp) 
    fstps -60(%ebp) 
    flds -32(%ebp) 
    flds -20(%ebp) 
    flds -28(%ebp) 
    flds -16(%ebp) 
    fxch %st(3) 
    fmulp %st, %st(2) 
    flds -24(%ebp) 
    flds -12(%ebp) 
    fxch %st(2) 
    fmulp %st, %st(4) 
    call L3 
"L00000000001$pb": 
L3: 
    popl %ebx 
    fmulp %st, %st(1) 
    fxch %st(3) 
    fmuls -68(%ebp) 
    fxch %st(1) 
    faddp %st, %st(2) 
    fxch %st(3) 
    fmuls -72(%ebp) 
    fxch %st(1) 
    faddp %st, %st(2) 
    fxch %st(1) 
    leal LC6-"L00000000001$pb"(%ebx), %eax 
    fstpl 12(%esp) 
    flds -64(%ebp) 
    fmuls -60(%ebp) 
    fxch %st(1) 
    faddp %st, %st(2) 
    faddp %st, %st(1) 
    fstpl 4(%esp) 
    movl %eax, (%esp) 
    call L_printf$stub 
    addl $96, %esp 
    xorl %eax, %eax 
    popl %ebx 
    popl %esi 
    leave 
    ret 
    .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 
L_printf$stub: 
    .indirect_symbol _printf 
    hlt ; hlt ; hlt ; hlt ; hlt 
    .subsections_via_symbols 

你的一部分有兴趣在标签L3之前开始。