簡體   English   中英

一個循環中,該循環執行多少條指令?

[英]How many instructions are executed in this loop in one cycle?

交流回路是

  while( *from)
  {
    *to++ = *from++;
  }

我想我基本上想知道*to++ = *from++;哪條MIPS指令*to++ = *from++; 轉換為。 我的結果是指令是14:

$L2:
   lw    $2,12($fp)
   lb    $3,0($2)
   bne    $3,$0,$L4
   j    $L3
$L4:
   lw    $2,8($fp)
   addu    $3,$fp,12
   lw    $4,0($3)
   lbu    $5,0($4)
   sb    $5,0($2)
   addu    $4,$4,1
   sw    $4,0($3)
   addu    $2,$2,1
   sw    $2,8($fp)
   j    $L2

通過查看完整的C程序,我得出了以下結論:

/* strcpy.c */

#include <stdio.h>
#include <idt_entrypt.h>

/* C stringcopy */

static void str_cpy( char *to, const char *from)
{
  while( *from)
  {
    *to++ = *from++;
  }
  *to = '\0';
}

int main()
{
  static char* hello = "Hello World!";
  static char to[4711] = "blaha blaj blurk bletch";
  int Time;

  printf("Strangen hello ser ut sa har: %s\n", hello);
  flush_cache();          /* toem cache-minnet */
  timer_start();          /* nollstall tidmatning */

  str_cpy( to, hello);

  Time = timer_stop();            /* las av tiden */
  printf("Time to copy: %d\n",Time);
  printf("Och kopian sa har: %s\n", to);
}

將其編譯為MIPS程序集,結果如下:

    .file   1 "strcpy.c"

 # -G value = 8, Cpu = 3000, ISA = 1
 # GNU C version cygnus-2.7.2-970404 (mips-mips-ecoff) compiled by GNU C version cygnus-2.7.2-970404.
 # options passed:  -msoft-float
 # options enabled:  -fpeephole -ffunction-cse -fkeep-static-consts
 # -fpcc-struct-return -fcommon -fverbose-asm -fgnu-linker -msoft-float
 # -meb -mcpu=3000

gcc2_compiled.:
__gnu_compiled_c:
    .text
    .align  2
    .ent    str_cpy
str_cpy:
    .frame  $fp,8,$31       # vars= 0, regs= 1/0, args= 0, extra= 0
    .mask   0x40000000,-8
    .fmask  0x00000000,0
    subu    $sp,$sp,8
    sw  $fp,0($sp)
    move    $fp,$sp
    sw  $4,8($fp)
    sw  $5,12($fp)
$L2:
    lw  $2,12($fp)
    lb  $3,0($2)
    bne $3,$0,$L4
    j   $L3
$L4:
    lw  $2,8($fp)
    addu    $3,$fp,12
    lw  $4,0($3)
    lbu $5,0($4)
    sb  $5,0($2)
    addu    $4,$4,1
    sw  $4,0($3)
    addu    $2,$2,1
    sw  $2,8($fp)
    j   $L2
$L3:
    lw  $2,8($fp)
    sb  $0,0($2)
$L1:
    move    $sp,$fp         # sp not trusted here
    lw  $fp,0($sp)
    addu    $sp,$sp,8
    j   $31
    .end    str_cpy
    .rdata
    .align  2
$LC0:
    .ascii  "Hello World!\000"
    .sdata
    .align  2
hello.4:
    .word   $LC0
    .data
    .align  2
to.5:
    .ascii  "blaha blaj blurk bletch\000"
    .space  4687
    .rdata
    .align  2
$LC1:
    .ascii  "Strangen hello ser ut sa har: %s\n\000"
    .align  2
$LC2:
    .ascii  "Time to copy: %d\n\000"
    .align  2
$LC3:
    .ascii  "Och kopian sa har: %s\n\000"
    .text
    .align  2
    .globl  main
    .ent    main
main:
    .frame  $fp,32,$31      # vars= 8, regs= 2/0, args= 16, extra= 0
    .mask   0xc0000000,-4
    .fmask  0x00000000,0
    subu    $sp,$sp,32
    sw  $31,28($sp)
    sw  $fp,24($sp)
    move    $fp,$sp
    jal __main
    la  $4,$LC1
    lw  $5,hello.4
    jal printf
    jal flush_cache
    jal timer_start
    la  $4,to.5
    lw  $5,hello.4
    jal str_cpy
    jal timer_stop
    sw  $2,16($fp)
    la  $4,$LC2
    lw  $5,16($fp)
    jal printf
    la  $4,$LC3
    la  $5,to.5
    jal printf
$L5:
    move    $sp,$fp         # sp not trusted here
    lw  $31,28($sp)
    lw  $fp,24($sp)
    addu    $sp,$sp,32
    j   $31
    .end    main

因此,我對以上內容進行了分析,發現在while循環的一個周期中執行的指令數為14。我的推理正確嗎?

$L2:
 lw    $2,12($fp)  ;  12($fp) is 'from' - load it in to $2
 lb    $3,0($2)    ; read a byte
 bne    $3,$0,$L4  ; if it's non-zero, jump into the main loop
 j    $L3          ; otherwise exit (this is the while clause)
$L4:
 lw    $2,8($fp)   ; 8($fp) is 'to' - load it into $2
 addu    $3,$fp,12 ; Load the address of 'from' into $3
 lw    $4,0($3)    ; Load 'from' into $4
 lbu    $5,0($4)   ; Read the byte again (this is the = *from)
 sb    $5,0($2)    ; Store the byte (*to = )
 addu    $4,$4,1   ; increment from (from++)
 sw    $4,0($3)    ; store it back
 addu    $2,$2,1   ; increment to (to++)
 sw    $2,8($fp)   ; store it back
 j    $L2          ; do it all again

因此,由於j $ L3被跳過,因此循環中有13個操作。

但是,正如markgz所指出的,MIPS具有分支延遲槽,這可能需要編譯器或匯編器添加nops或switch指令。 您應該查看最終代碼的反匯編以及中間匯編程序的輸出。

在這種情況下,很可能在最初的bne指令之后至少會有一個額外的nop,但是匯編程序可能會重新排序最后的跳轉,而不是使用nop填充。 因此,如果您查看最終輸出,則可能總共有14條指令。

那里有很多冗余-一半指令只是加載/存儲回本地變量,而不是僅僅將內容保留在寄存器中。 這是典型的調試/未優化構建。

看起來正確。

似乎有很多多余的負載和存儲-優化是否完全關閉?

實際上,該while循環的執行中只有13個操作(操作j $L3僅在while結束時執行)。

您在計數中包括了測試和條件跳轉指令,這對我來說似乎不合適。

已經有一個分支在您的代碼中太多了。 嘗試

  while ((*to++ = *from++));

我的編譯器(x86的gcc)產生的更好的代碼只有一個條件跳轉。 在一種可以編譯為的架構(似乎具有更好的尋址模式)上

    xorl    %eax, %eax
.L8:
    movzbl  (%rsi,%rax), %edx
    movb    %dl, (%rdi,%rax)
    addq    $1, %rax
    testb   %dl, %dl
    jne .L8
    ret

因此,這里的內部只有三個指令和一個初始化,因為增量僅在循環內執行一次,而不是兩次。 通常,在問這樣的問題時,您必須要小心,實際上(*to++ = *from++)本身並沒有花費,而只是嵌入到周圍的代碼中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM