0

谢谢大家对我的耐心。我只需要把头绕在我正在看的东西上。为缓慢而道歉,只是试图学习和理解。

在重新阅读了每个人的评论并查看了几次代码后,我意识到我的问题指向了错误的方向。我

我会用简单的组装说明替换这两行吗?还是我必须做类似的事情asm()。我想这就是我感到困惑的地方。一旦我知道了这一点,我想我会从那里得到它。

编辑
我没有意识到我从帖子中省略了这个。显然是最重要的部分,感谢 Oli 指出。

目标是用内联汇编代码替换附加程序中 for 循环内的两行代码。您必须从内联汇编代码中获得相同的输出。(执行相同的结果,循环次数相同)

C :

#include "stdlib.h"
#include "time.h"

int main (int argc, char* argv[])
{
    int num1 = 10;
    int num2 = 27;
    int sum = 0;
    int cases = 0;
    int loose = 0;
    float time1 = 0;
    float time2 = 0;
    float time = 0;
    int i = 0;

    sum = num1 + num2;

    asm("xor %%eax,%%eax;"
        "mov %1,%%eax;"
        "add %2,%%eax;"
        "mov %%eax,%0;"
        :"=r"(sum)                   /* outputs */
        :"r"(num1),"r"(num2)         /* input   */
        :"%eax");                    /*clobber list*/

    printf("The sum is %d \n",sum);

    time1 = clock();
    for (i = 0; i<1000000000; i++)
    { 

        cases = i/num1;
        loose = i%num1;

    }  
    printf("The number of cases are %d \n",cases);
    printf("The number of loose items are %d \n",loose);

    time2 = clock();

    time = (time2 - time1) / CLOCKS_PER_SEC;

    printf("The elapsed time is %f seconds \n", time);

    system("pause");
    return 0;
}



集会 :

.file   "inlineAsm.c"
.def    ___main;    .scl    2;  .type   32; .endef
.section .rdata,"dr"

LC1:
    .ascii "The sum is %d \12\0"
LC2:
    .ascii "The number of cases are %d \12\0"
    .align 4
LC3:
    .ascii "The number of loose items are %d \12\0"
    .align 4
LC5:
    .ascii "The elapsed time is %f seconds \12\0"
LC6:
    .ascii "pause\0"
    .align 4
LC4:
    .long   1148846080
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef

_main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $56, %esp
    andl    $-16, %esp
    movl    $0, %eax
    addl    $15, %eax
    addl    $15, %eax
    shrl    $4, %eax
    sall    $4, %eax
    movl    %eax, -40(%ebp)
    movl    -40(%ebp), %eax
    call    __alloca
    call    ___main
    movl    $10, -4(%ebp)
    movl    $27, -8(%ebp)
    movl    $0, -12(%ebp)
    movl    $0, -16(%ebp)
    movl    $0, -20(%ebp)
    movl    $0x00000000, %eax
    movl    %eax, -24(%ebp)
    movl    $0x00000000, %eax
    movl    %eax, -28(%ebp)
    movl    $0x00000000, %eax
    movl    %eax, -32(%ebp)
    movl    $0, -36(%ebp)
    movl    -8(%ebp), %eax
    addl    -4(%ebp), %eax
    movl    %eax, -12(%ebp)
    movl    -4(%ebp), %ecx
    movl    -8(%ebp), %edx
/APP
    xor %eax,%eax;mov %ecx,%eax;add %edx,%eax;mov %eax,%edx;
/NO_APP
    movl    %edx, %eax
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC1, (%esp)
    call    _printf
    call    _clock
    pushl   %eax
    fildl   (%esp)
    leal    4(%esp), %esp
    fstps   -24(%ebp)
    movl    $0, -36(%ebp)
L2:
    cmpl    $999999999, -36(%ebp)
    jg  L3
    movl    -36(%ebp), %edx
    leal    -4(%ebp), %ecx
    movl    %ecx, -40(%ebp)
    movl    %edx, %eax
    movl    -40(%ebp), %ecx
    cltd
    idivl   (%ecx)
    movl    %eax, -40(%ebp)
    movl    -40(%ebp), %eax
    movl    %eax, -16(%ebp)
    movl    -36(%ebp), %edx
    leal    -4(%ebp), %ecx
    movl    %ecx, -40(%ebp)
    movl    %edx, %eax
    movl    -40(%ebp), %ecx
    cltd
    idivl   (%ecx)
    movl    %edx, -20(%ebp)
    leal    -36(%ebp), %eax
    incl    (%eax)
    jmp L2
L3:
    movl    -16(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC2, (%esp)
    call    _printf
    movl    -20(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC3, (%esp)
    call    _printf
    call    _clock
    pushl   %eax
    fildl   (%esp)
    leal    4(%esp), %esp
    fstps   -28(%ebp)
    flds    -28(%ebp)
    fsubs   -24(%ebp)
    flds    LC4
    fdivrp  %st, %st(1)
    fstps   -32(%ebp)
    flds    -32(%ebp)
    fstpl   4(%esp)
    movl    $LC5, (%esp)
    call    _printf
    movl    $LC6, (%esp)
    call    _system
    movl    $0, %eax
    leave
    ret
    .def    _system     ;.scl   3;  .type   32; .endef
    .def    _clock      ;.scl   3;  .type   32; .endef
    .def    _printf     ;.scl   3;  .type   32; .endef



输出 :

/*
The sum is 37
The number of cases are 99999999
The number of loose items are 9
The elapsed time is 9.359000 seconds
Press any key to continue . . .
*/
4

2 回答 2

1

看起来对您的程序最好的优化是简单地删除所有内联汇编,因为它与sum = num1 + num2;上面的语句做同样的事情 - 作为奖励,您的程序也将变得更加可移植!

于 2012-05-07T23:43:30.883 回答
1

根据您在最近编辑中添加的信息,您需要修改循环内的代码以使程序更快。

在我看来,程序运行缓慢的原因是它无缘无故地循环了 1000000000 次。

显然,最好的办法是完全消除循环。但是,如果您仅限于修改循环内的代码,您是否可以让循环在除最后一次之外的每次迭代中都执行 NOOP?

注意:这是一个足够奇怪的问题,我仍然认为对赋值的参数可能存在一些误解。

编辑:让我们看一下内联汇编:

asm("xor %%eax,%%eax;"
    "mov %1,%%eax;"
    "add %2,%%eax;"
    "mov %%eax,%0;"
    :"=r"(sum)                   /* outputs */
    :"r"(num1),"r"(num2)         /* input   */
    :"%eax");                    /*clobber list*/

出于优化的目的,您需要了解的最重要的事情是它只运行一次。不仅如此,它还进行了一个极其简单和快速的操作,如果它是用 C 编写的,它可能同样简单和快速。除了让程序更复杂之外,拥有这个内联汇编没有任何意义,这是我的另一个原因觉得这个作业有些奇怪。它似乎充满了红鲱鱼。

让我们逐行看汇编程序。

第一行是清零%eax寄存器的简写方式。如果你xor有自己的东西,结果总是零。(我不知道为什么需要在这里,因为您正在覆盖%eax下一行的内容。)

第二行加载%eax变量 1,即第一个输入 ( num1)。

第三行将变量 2 ( num2) 添加到%eax.

第四行将加载的结果复制%eax到输出变量 ( sum)。

剩下的几行定义了我们刚刚提到的变量,顺序为 (0, 1, 2),并且还告诉编译器您刚刚使用了该%eax寄存器,因此在接下来使用它之前必须将其清除。

您可以轻松地用 C 中的简单添加替换所有该汇编程序,并且不会更慢。编译器非常聪明。

基本上,您应该需要使用内联汇编程序的唯一情况是在一个循环中,该循环代表您的程序的大部分处理时间,在您知道编译器优化不佳的代码中。这个内联汇编器在这两个方面都不符合条件。尤其是因为它确实与它正上方的 C 行完全相同!您可以完全删除 asm() 调用,而根本不更改程序的输出。

如果您的任务是使您的程序明显更快,但仅限于编辑该内联汇编程序,那么您是在做傻事。

于 2012-05-07T23:59:45.590 回答