push と pop は、アセンブラに対する疑似命令であり、実際の命令ではありません。ベース レジスタが stm で更新されたストアを取得します。
push {r11}
stmdb r13!,{r11}
push {r10-r12}
stmdb r13!,{r10-r12}
同じ命令に対して stmfd よりも stmdb を好みますが、構文が異なるだけです。(stmdb と ldmia は私には理にかなっています。前に減少し、後に増加します)。
組み立ててから分解。
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e92d0800 stmfd sp!, {fp}
8: e92d1c00 push {sl, fp, ip}
c: e92d1c00 push {sl, fp, ip}
stmエンコーディングを調べるか、ビットを見て考えてみると、命令0xe92dの上位ビットはstmia/fdであり、下位ビットはどのレジスタを保存するかを示すフラグです。 11 を押すと、次に 8 と c でそのビットが r11 に設定され、次にその下のビットが r10 に設定され、その上のビットが r12 に設定されます。
push と pop は、 sp を使用して ! を使用することを覚えようとするよりも読みやすいです。レジスタの後に、ia/db/fd などのサフィックスなどを覚えておいてください。
親指には実際のプッシュ/ポップがあると思います。
arm の単一のレジスタ バリアントが単一のストアに変わった場合、stm を 1 つの命令で使用するか、str で使用するかに関係なく、操作は機能的に同等です。
操作後にr13を更新し、stmにdbまたはfdを使用する限り、疑似命令または実際の命令を使用できます。
複数のレジスタを保存/復元する場合は、それらを 1 つの命令で確実にリストします。複数のプッシュまたはポップのリストを作成しないでください。
no:
push {r10}
push {r11}
push {r12}
yes:
push {r10-r11}
r0-r7+r14 をプッシュし、r0-r7+r15 をポップしてより高いレジスタを保存することしかできないため、経験がない限り、それらをより低いレジスタにコピーしてからプッシュを使用する必要があります。そして、stmをプッシュする必要があり、r13を使用できません。(thumb2 は、アーキテクチャで使用できる拡張機能に応じて、腕のようなエクスペリエンスを提供します)。
あなたの質問を読み直して
sp はスタック ポインタ r13 です。疑似命令は正しい命令を選択するので、stm と str について心配する必要はありません。複数のレジスタを保存すると、最新のアーム システムで最適化を「行うことができます」が、保証はされません。amba/axi バスが 64 ビット幅の場合、一度に 32 ビットを書き込むよりも、一度に 64 ビットを書き込む方が 2 倍以上高速です。 32 ビットの書き込みですが、64 ビットの書き込みはそうではありません (キャッシュの動作は無視してください)。stm がアラインされたアドレスにある場合 (スタックを使用する場合、それを理解するのにコードが多すぎますが、心配しないでください)、2 つのレジスターのプッシュは、2 つの別々のプッシュよりも著しく高速です (コアがそれらを最適化しない限り) 1 バス サイクル)。4 つのレジスタをプッシュすると、アライメントされていない場合に 3 つのうちの 1 つが発生し、アライメントされていないアドレス (0x1004 など) で 32 ビットの転送が 3 回行われ、その後、アライメントされたアドレス (0x1008) で 64 ビットの転送が行われ、次に 32最後のレジスタ (0x1010) のビット転送。その 4 つのレジスタ プッシュがアラインされたアドレスで行われた場合、2 つの別々の 64 ビット転送のいずれかが発生します。つまり、2 つのレジスタを 0x2010 に転送し、2 つのレジスタを 0x2018 に転送するか、長さ 2 の転送 (1 回の転送で 2 つの 64 ビット項目)アラインされたベースアドレス、たとえば 0x2010。4 つの個別の 32 ビット転送という最悪のケースは発生しないため、stm/push を使用する価値があります。次に、最後のレジスタ (0x1010) の 32 ビット転送。その 4 つのレジスタ プッシュがアラインされたアドレスで行われた場合、2 つの別々の 64 ビット転送のいずれかが発生します。つまり、2 つのレジスタを 0x2010 に転送し、2 つのレジスタを 0x2018 に転送するか、長さ 2 の転送 (1 回の転送で 2 つの 64 ビット項目)アラインされたベースアドレス、たとえば 0x2010。4 つの個別の 32 ビット転送という最悪のケースは発生しないため、stm/push を使用する価値があります。次に、最後のレジスタ (0x1010) の 32 ビット転送。その 4 つのレジスタ プッシュがアラインされたアドレスで行われた場合、2 つの別々の 64 ビット転送のいずれかが発生します。つまり、2 つのレジスタを 0x2010 に転送し、2 つのレジスタを 0x2018 に転送するか、長さ 2 の転送 (1 回の転送で 2 つの 64 ビット項目)アラインされたベースアドレス、たとえば 0x2010。4 つの個別の 32 ビット転送という最悪のケースは発生しないため、stm/push を使用する価値があります。