Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

NOP

前のセクションでプログラムをリリースモードでコンパイルし、実際に逆アセンブル結果を見たのであれば、 delay 関数が最適化によって取り除かれ、main の内部からは一度も呼び出されていないことに 気づいたはずです。

LLVM は、その関数は何も価値のあることをしていないと判断し、単に削除しました。

LLVM が for ループによる遅延を最適化しないようにする方法があります。volatile なアセンブリ命令を 追加することです。どんな命令でも構いませんが、この場合は副作用がないため、NOP(No OPeration)は 特に適した選択です。

for ループによる遅延は次のようになります。

#![allow(unused)]
fn main() {
#[inline(never)]
fn delay(_tim6: &tim6::RegisterBlock, ms: u16) {
    const K: u16 = 3; // この値は調整が必要です
    for _ in 0..(K * ms) {
        aux9::nop()
    }
}
}

そして今度は、プログラムをリリースモードでコンパイルしても、delay は LLVM によって 取り除かれません。

$ cargo objdump --bin clocks-and-timers --release -- -d --no-show-raw-insn
clocks-and-timers:      file format ELF32-arm-little

Disassembly of section .text:
clocks_and_timers::delay::h711ce9bd68a6328f:
 8000188:       push    {r4, r5, r7, lr}
 800018a:       movs    r4, #0
 800018c:       adds    r4, #1
 800018e:       uxth    r5, r4
 8000190:       bl      #4666
 8000194:       cmp     r5, #150
 8000196:       blo     #-14 <clocks_and_timers::delay::h711ce9bd68a6328f+0x4>
 8000198:       pop     {r4, r5, r7, pc}

では、これを試してみましょう。プログラムをデバッグモードでコンパイルして実行し、その後で プログラムをリリースモードでコンパイルして実行してください。両者の違いは何でしょうか。 その違いの主な原因は何だと思いますか。両者を同等に、あるいは少なくとも再びもっと似たものにする 方法を思いつきますか。