2012-05-07 14 views
0

皆さんありがとうございました。私はちょうど私が見ていたものの周りに私の頭を包んでいなければならなかった。ゆっくりと謝り、学び、理解しようとするだけです。このインラインアセンブリの効率を上げるために、アドバイスを提供することはできますか?

誰もがコメントを読んで、コードを何度か見てから、私の質問が間違った方向に向けられていたことに気付きました。 I

簡単なアセンブリ命令で2行を置き換えることはできますか?または、私はasm()のような何かをしなければならないでしょうか?私はこれが私が混乱しているところだと思います。私がこれを知ったら、そこからそれを取ると思う。

EDIT
私はポストからこれを省略実現しませんでした。明らかに、最も重要な部分は、それを指摘するためにオリーに感謝します。

目的は、添付されたプログラムの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 . . . 
*/ 
+1

これはおそらくhttp://codereview.stackexchange.comに適しています –

+0

このコードの目的は何ですか?なぜインラインアセンブラがループの外側にあるのでしょうか(明らかに)繰り返し1000000000回ですか? –

+0

@BrianRoachリンクをありがとう、私はそれをチェックし、そこに投稿します。 – StartingGroovy

答えて

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言語で書かれていれば、シンプルで速い操作が可能な非常に簡単で高速な操作をしています。このインラインアセンブリーでは、プログラムを複雑にする点以外はありません。この課題について何か不思議なことがあると思う。赤ちゃんがいっぱいです。

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

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

2行目は、最初の入力(num1)である変数1、と%eaxをロードします。

3行目には、%eaxに変数2(num2)が追加されています。

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

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

Cで簡単に追加するだけで、すべてのアセンブラを簡単に置き換えることができますし、遅くなることもありません。コンパイラは非常にスマートです。

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

あなたのプログラムを著しく速くするが、そのインラインアセンブラだけを編集することに制限されている場合、あなたは愚かなことにはならない。

+0

@AndfrewGインラインアセンブリのスニペットは何を説明できますか?私にとっては、関数の呼び出しのように見えますが、パラメータを理解できません。それは私の出発点になり、そこから私の道を作ることができます – StartingGroovy

+0

私は正しい形式を使用できるように私の答えを編集します。 –

+0

ありがとう、少し助けてください。最後に、 '%'は何をしますか?これは学習用ですので、プログラムが時間の無駄に見えるかもしれませんが、主な目的はインラインアセンブリを扱い、それがどのようなものかを見ることです。 – StartingGroovy

1

あなたのプログラムのための最高の最適化は、それだけで、上記のステートメントsum = num1 + num2;と同じことを行うように単ににインラインアセンブリのすべてを削除することですように見えます - ボーナスとして、あなたのプログラムはよりポータブルになります!

+0

私はCでそれをやり直したいと思います。私の知識)それを改善する。 – StartingGroovy

+0

プログラムの意味が少ししかないので、私は割り当ての目的について何らかの間違いや誤解があると思う傾向があります。 –

+0

@AndrewG。あなたは正しいです、私は投稿を編集しました。その人には申し訳ありません。(私はCで頻繁に遊んでいないので、各行が何をしているのか把握しようとしていました) – StartingGroovy

関連する問題