0

我慢してくれてありがとう。見ているものに頭を巻くだけでした。ただ学び、理解しようとしているだけで、遅くなってしまったことをお詫びします。

みんなのコメントを読み直し、コードを数回見た後、私の質問が間違った方向に向けられていたことがわかりました。私

2つのラインを簡単な組み立て手順に置き換えますか?または私はのようなことをしなければならないでしょうかasm()。これが私が混乱しているところだと思います。これを知ったら、そこから取っていくと思います。

編集
私はこれを投稿から省略したことに気づいていませんでした。明らかに最も重要な部分は、それを指摘してくれたOliに感謝します。

目標は、添付プログラムのforループ内の2行のコードをインラインアセンブリコードに置き換えることです。インラインアセンブリコードから同じ出力を取得する必要があります。(同じループ数で同じ結果を実行します)

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

最近の編集で追加した情報に基づいて、プログラムを高速化するためにループ内のコードを変更する必要があります。

プログラムが遅いのは、理由もなく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*/

最適化の目的で、これについて知っておく必要がある最も重要なことは、1回だけ実行されるということです。それだけでなく、Cで記述した場合と同じように単純で高速な、非常に単純で高速な操作を実行します。プログラムをより複雑にする以外に、このインラインアセンブリを使用しても意味がありません。これが、もう1つの理由です。この割り当てには何か奇妙なことがあると思います。赤いニシンだらけのようです。

アセンブラを1行ずつ見ていきましょう。

%eax最初の行は、レジスタをゼロにする簡単な方法です。あなたxorがそれ自体で何かをしている場合、結果は常にゼロです。(次の行の内容を上書きしているので、なぜこれがここにある必要があるのか​​わかりません%eax。)

%eax2番目の行には、最初の入力()である変数1がロードされますnum1

num23行目は、変数2( )をに追加します%eax

%eax4行目は、にロードされた結果を出力変数( )にコピーしますsum

残りの行は、(0、1、2)の順序で参照した変数を定義し、レジスターを使用したことをコンパイラーに通知する%eaxため、次に使用する前にレジスターをクリアする必要があります。

そのすべてのアセンブラをCでの単純な追加に簡単に置き換えることができ、遅くなることはありません。コンパイラは非常に賢いです。

基本的に、インラインアセンブラを使用する必要がある唯一のケースは、コンパイラが最適化されていないことがわかっているコードで、プログラムの処理時間の大部分を表すループ内です。このインラインアセンブラは、どちらのカウントにも当てはまりません。特にそれは文字通りその真上のCラインとまったく同じことをするので!asm()呼び出しを完全に削除し、プログラムの出力をまったく変更しないようにすることができます。

プログラムを著しく高速化する必要があるが、そのインラインアセンブラのみの編集に制限されている場合は、ばか者の用事になります。

于 2012-05-07T23:59:45.590 に答える
1

プログラムの最適化として最適なのは、インラインアセンブリをすべて削除することです。これは、上記のステートメントと同じことを行うためですsum = num1 + num2;。ボーナスとして、プログラムの移植性も向上します。

于 2012-05-07T23:43:30.883 に答える