我在這個網站上找到了一個代碼片段作為一個問題的答案。該代碼在 MIPS 中使用嵌套回圈。
這是代碼:
.data
prompt: .asciiz "Please enter the edge length of the base of right
triangle: "
newLine: .asciiz "\n"
star: .asciiz "*"
.text
main:
li $v0, 4 # print the prompt
la $a0, prompt
syscall
li $v0,5 #take user input
syscall
move $s0, $v0 # move the input to $s0
li $t0, 0 # load 0 at t0
outerLoop:
beq $t0, $s0, end #(for i=0;i<=baseLength;i )
#if t0=s0 branch to end
addi $t0, $t0, 1 # increment i
li $t1, 1 #load 1 at t1
jal changeLine #jump to changeLine
innerLoop:
bgt $t1, $t0, outerLoop #(for j=0;j<=i;j )
# if t1=t0 branch to outerLoop
li $v0, 4 # print star
la $a0, star
syscall
addi $t1, $t1, 1 # increment j
j innerLoop # jump to innerLoop
changeLine:
li $v0, 4 # new line
la $a0, newLine
syscall
jr $ra # jump to after the call instruction
end:
li $v0, 10 # end of program
syscall
代碼運行良好,但我無法理解外回圈如何迭代,即使沒有像j outerLoop.
任何幫助表示贊賞。
uj5u.com熱心網友回復:
答案是innerLoop的第一條陳述句:
innerLoop:
bgt $t1, $t0, outerLoop #(for j=0;j<=i;j )
# if t1=t0 branch to outerLoop
當innerLoop的總迭代次數結束時,代碼跳回到outerLoop標簽。
uj5u.com熱心網友回復:
事情是這樣的:外部回圈已經“優化”,不再直接反映評論中宣告的 for 回圈。C 等效項看起來更像這樣:
for ( i = 0; i <= baseLength; /* empty increment */ ) {
i ;
<loop-body> // includes inner loop
}
通常像這樣的 for 回圈:
for ( i = 0; i < N; i ) { <loop-body> }
根據 for 回圈結構的定義,將擴展如下:
i = 0;
while ( i < N ) {
<loop-body>
i ;
}
然而,正如你所看到的,在你展示的代碼中,i 增量已經從后移loop-body前至loop-body。
因此,在執行內回圈后,外回圈沒有要執行的增量代碼——因此,內回圈的退出位置可以直接從外回圈的頂部繼續。
但是,在進行這些更改時,我們必須小心 b/c 現在loop-body執行的值i比從其翻譯并現在在注釋中顯示的 C 代碼中的值大 1 。如果i在里面使用,loop-body這是一個問題。
而這里i確實是在回圈體內部使用的,作為內部回圈迭代控制的一部分。因為i是一個更大的,這個內部回圈將比在注釋中撰寫的 C 代碼多迭代一次。
如果未應用“優化”,則內回圈可能會通過向前跳到i 屬于外回圈的增量而退出,然后j outerLoop(向后跳)如您所料,繼續外回圈。
初級匯編程式員通常熱衷于修改他們在轉換為匯編期間開始使用的 C 或偽代碼,但這些更改通常在不了解它們在邏輯或演算法上不等效的情況下完成。例如,將while回圈改為do-while回圈;將陣列參考更改為指標操作 - 在這種情況下更改操作順序。由于 C 可以表達所有這些(do-while、指標等),我主張首先在 C 中進行優化,然后驗證等效行為,并將其用于匯編。
是的,還有其他優化僅在匯編中才有意義(即在 C 中不可能或不實用),但建議將它們留在效率是主要主題的情況下,然后按照 C 開始代碼而不是字面意思進行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/368644.html
上一篇:如何解釋這個圖函式演算法?
