やまものブログ

メモ書きブログです (^_^;A

ARM アセンブラ BLX/BX で Thumb コード混在

末尾が X のブランチ命令
BLX (Branch with Link and eXchange)
BX (Branch and eXchange)
では ARM <--> Thumb モードの切替ができます。

BLX/BX ともにレジスタあるいはラベルをオペランドに指定できますが、ARM Compiler toolchain Assembler Reference によると、
BLX label always changes the state.
とのことなので、ラベルを使うと常にモードが切り替わるようです。

下記のコードで試してみました。
mrs.s
.text
.global _start
_start:
	mrs	r0, apsr
	blx	mrs_t
	mov	r0, #0
	mov	r7, #1
	svc	#0

mrs_t.s
.text
.global mrs_t
mrs_t:
	mrs	r0, apsr
	bx	lr

ビルドは以下のコマンドで、mrs_t.s を Thumb でコンパイルしています。
arm-xilinx-linux-gnueabi-as -g -o mrs.o mrs.s 
arm-xilinx-linux-gnueabi-as -mthumb -g -o mrs_t.o mrs_t.s 
arm-xilinx-linux-gnueabi-ld  mrs.o mrs_t.o

gdb でステップ実行しながら CPSR の値を確認しました。
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
_start () at mrs.s:4
4		mrs	r0, apsr
(gdb) print /x $cpsr
$1 = 0x10
(gdb) s
6		blx	mrs_t
(gdb) print /x $cpsr
$2 = 0x10
(gdb) s
mrs_t () at mrs_t.s:4
4		mrs	r0, apsr
(gdb) print /x $cpsr
$3 = 0x30
(gdb) s
5		bx	lr
(gdb) print /x $cpsr
$4 = 0x30
(gdb) s
_start () at mrs.s:8
8		mov	r0, #0
(gdb) print /x $cpsr
$5 = 0x10
(gdb) c
Continuing.
[Inferior 1 (process 952) exited normally]
(gdb) quit


$cpsr が 0X30 を示している部分がありますが、以下のとおり期待通りですhttps://cdn-ak.f.st-hatena.com/images/fotolife/w/wyamamo/20190812/20190812204706.gif
bit[5] = T bit (Thumb state)
bit[4:0] = M[4:0] プロセッサモード → 10000 は Userモード