[英]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.