免責事項 : 私は asm 初心者です。完全に理解するには、おそらく2の補数または何かを確認する必要があります:(
私は次の目的について混乱しています:
....
BL some_func
MOV R3, R0,LSL#16
MOVS R3, R3,LSR#16
....
なぜシフトバック?そして動き?
r0 &= 0xFFFF を実行するには 3 つの命令が必要です。
mov r3,#0x00FF または r3,r3,#0xFF00 およびr0、r0、r3
したがって、前後のシフトはより効率的です。
あなたが行っていたのは 16 ビット変数に関連したものであるため、正確を期すために、コンパイラはプログラムを適切に動作させるために上位ビットを切り捨てなければなりません。int などを使用していた場合、これは行われなかった可能性があります。それがこれらの指示をどのように扇動したかはわかりません。
符号拡張を行うためにこれを目にすることがありますが、これは算術シフトではなく、論理シフトです (キャリー ビットではなくゼロが入ります)。
多分あなたのコードは if(hello&0xFFFF) then のようなことをしました。
ARM は、このようなコードが他に何もない場合、パフォーマンス上の理由から、指示しない限りフラグを正常に更新しません。
if(a&0xFF) b=0x12; そうでなければ b=0x34; 次のようになります。 ands r0,r0,#0xFF movne r1,#0x12 moveq r1,#0x34
他のプロセッサでは、 と は常にフラグを設定し、次の命令はパイプ フラッシュを引き起こす分岐になります。
ands r0,r0,#0xFF bne notequal mov r1,#0x12 bは等しい 注意: mov r1,#0x34 等しい:
実行されると、はるかに残忍です。多くのプロセッサは、フラグを即時移動で上書きしますが、アームはこれを行いません。(親指モードは別の話です)。
分岐のみが条件フィールドを持つのではなく、アーム上のすべての命令に条件フィールドがあり、等しい場合は分岐し、等しい場合は加算、等しい場合はサブ、キャリー セットの場合は分岐、キャリー セットの場合は分岐などがあります。フラグを変更できる命令には、フラグの更新を有効または無効にするオペコード ビットがあります。s を命令に追加します。and r0,r1,r2 はフラグを更新しませんが、ands r0,r1,r2 はフラグを更新します。
したがって、2 つの命令は 2 つのことを行い、レジスタの上位 16 ビットをゼロにしてから、その後に続く条件のフラグを設定しました。等しい場合はブランチ、等しくない場合はブランチである可能性が高い mov の場合。これを生成した元のソース コードはどのようなものでしたか?
左シフトでは、オーバーフローしたビットは失われます。したがって、32-16 = 16 桁目より上のすべてのビットは、右シフト後にゼロになります。
r0 = aaaabbbbccccdddd eeeeffffgggghhhh
lsl, 16 -> aaaabbbbccccdddd eeeeffffgggghhhh 0000000000000000
(overflowed)
-> eeeeffffgggghhhh 0000000000000000
lsr, 16 -> eeeeffffgggghhhh
命令は次と同等です
r3 = r0 & 0xffff;