LoginSignup
4
3

More than 5 years have passed since last update.

SHのPC相対について

Last updated at Posted at 2014-12-16

【追記】元記事が修正されました。

熱血!アセンブラ入門』の書籍の補足情報に以下の記述があります。

■ SHのPC相対について (2014/10/04)

PC相対によるメモリアクセスの際に,PCの値が4バイトアラインメントされて いるという記述がありますが,すみませんちょっと筆者の勘違いが残ってしまって いたようです.(情けない…)

sh-elf.dを実際に見てみたところ,以下のようになっているようです.

・ PC(プログラムカウンタ)は,2つ先の命令を指している.
・ mov.wで2バイトをPC相対でロードする際には,PC+オフセットで アドレスを計算している.(単純に加算するだけ)
・ mov.lで4バイトをPC相対でロードする際には,PCを4バイトアラインメント して,さらにオフセットを加算することでアドレスを計算している. (4バイトロードなので,アラインメントされる)

これについて検証してみました。

mov.w

mov.w命令で近くのメモリから値を読み込みます。

※ 機械語を見るためのコードで、実行は想定していません。

sh1.s
test0a:
    mov.w 0f,r0
    nop
0:  .word 0x7788

test0b:
    mov.w 0f,r0
    nop
0:  .word 0x7788

test1a:
    mov.w 0f,r0
    nop
    nop
0:  .word 0x7788

test1b:
    nop
    mov.w 0f,r0
    nop
    nop
0:  .word 0x7788

mov.w命令の相対アドレス(90 XXのXXの部分)に注目します。

逆アセンブル結果
00000000 <test0a>:
   0:   90 00           mov.w   4 <test0a+0x4>,r0   ! 7788
   2:   00 09           nop 
   4:   77 88           add #-120,r7

00000006 <test0b>:
   6:   90 00           mov.w   a <test0b+0x4>,r0   ! 7788
   8:   00 09           nop 
   a:   77 88           add #-120,r7

0000000c <test1a>:
   c:   90 01           mov.w   12 <test1a+0x6>,r0  ! 7788
   e:   00 09           nop 
  10:   00 09           nop 
  12:   77 88           add #-120,r7

00000014 <test1b>:
  14:   00 09           nop 
  16:   90 01           mov.w   1c <test1b+0x8>,r0  ! 7788
  18:   00 09           nop 
  1a:   00 09           nop 
  1c:   77 88           add #-120,r7

この結果を見ると、4バイトアラインメントの影響はなく、以下の記述は正しいようです。

・ PC(プログラムカウンタ)は,2つ先の命令を指している.
・ mov.wで2バイトをPC相対でロードする際には,PC+オフセットで アドレスを計算している.(単純に加算するだけ)

mov.l

mov.l命令で近くのメモリから値を読み込みます。

sh2.s
test0a:
    mov.l 0f,r0
    nop
0:  .long 0x778899aa

test0b:
    nop
    mov.l 0f,r0
0:  .long 0x778899aa

test1a:
    mov.l 0f,r0
    nop
    nop
    nop
0:  .long 0x778899aa

test1b:
    nop
    mov.l 0f,r0
    nop
    nop
0:  .long 0x778899aa

mov.l命令の相対アドレス(d0 XXのXXの部分)に注目します。

逆アセンブル結果
00000000 <test0a>:
   0:   d0 00           mov.l   4 <test0a+0x4>,r0   ! 778899aa
   2:   00 09           nop 
   4:   77 88           add #-120,r7
   6:   99 aa           mov.w   15e <test1b+0x142>,r9

00000008 <test0b>:
   8:   00 09           nop 
   a:   d0 00           mov.l   c <test0b+0x4>,r0   ! 778899aa
   c:   77 88           add #-120,r7
   e:   99 aa           mov.w   166 <test1b+0x14a>,r9

00000010 <test1a>:
  10:   d0 01           mov.l   18 <test1a+0x8>,r0  ! 778899aa
  12:   00 09           nop 
  14:   00 09           nop 
  16:   00 09           nop 
  18:   77 88           add #-120,r7
  1a:   99 aa           mov.w   172 <test1b+0x156>,r9

0000001c <test1b>:
  1c:   00 09           nop 
  1e:   d0 01           mov.l   24 <test1b+0x8>,r0  ! 778899aa
  20:   00 09           nop 
  22:   00 09           nop 
  24:   77 88           add #-120,r7
  26:   99 aa           mov.w   17e <test1b+0x162>,r9

この結果を見ると、以下の記述は少し補足が必要なように思います。

・ PC(プログラムカウンタ)は,2つ先の命令を指している.
・ mov.lで4バイトをPC相対でロードする際には,PCを4バイトアラインメント して,さらにオフセットを加算することでアドレスを計算している. (4バイトロードなので,アラインメントされる)

一般的にアラインメントでは切り上げすることが多いように思いますが、a: d0 001e: d0 01切り下げ切り捨てでアラインメントされています。というわけで「切り下げ」「切り捨て」を明記した方が誤解が少ないように思います。

【追記】「切り下げ」という言い方は一般的ではなく、普通は「切り捨て」と言うというご指摘を受けました。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3