版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
* z" E, _: a/ b7 y' N4 a4 M看优龙FS2410(s3c2410)的bootloader: vivi, 思考摸索了有段时间的问题,代码如何从cpu上的sram中跳到SDRAM中的,从而引发了一连串的问题,此文的目的就是问题之一。8 J, X1 Y# E) S* p2 K- _& E
代码里会看到如下的指令:
6 {( V. c! O6 \mov r1, #0x53000000
# I# U8 Z( [7 G3 }& B而我们知道arm指令是4字节长,上面这个指令光立即数就已经4个字节了,所以,汇编器如何把这条汇编语句变成二进制指令的呢?
6 a4 S- d3 M) m" O2 u3 F- M, K3 ~网络上答案很多,如下,不过原文有点小错误,已经高亮纠正: E/ w; T- o! T
- o* E, A' i' Z+ H ?' k原文戳我
' ?7 j- H9 y, P" ^% n转载Begin:
9 m- c7 ^. S# I0 jARM中的MOV指令格式是这样的$ ~: c0 n; _ J% k, ~
% f3 ]2 b K: l+ _* o5 ~$ |) Y* `. `( ?6 l* E- q
1 G) w) S0 {* {( z* C2 t
op2是占了12位,其中bit11-bit8是移位数(rotate),bit7-0是一个8位的立即数(imm),MOV Rn, op2,执行之后,Rn=op2 >> (rotate * 2),这里的移位是循环右移,这就决定了MOV指令不是所有的立即数都能表示的,以下是几个例子:7 {! J; e0 K' x# Z
$ [2 J% n& b0 D& o9 v5 F
0 o5 o# b8 l5 y- X4 H) y
9 O; F* h2 [. j, O. R' E. V1、mov r3, #0x56000000
* K/ @2 u. S* g* O" O$ @8 U# A z! i% ]8 V# r) e# W. O
虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码e3a03456,展开成二进制,对照下格式
1 A0 V* U7 G! V" J& {
) T1 `+ v4 W4 u! L1110 0011 1010 0000 0011 0100 0101 0110# U% ?* k8 q0 R. p
/ @" ~0 N: d3 L' M0 {9 l0 t6 c1 i9 b
cond[31:28]=11101 n$ p* f% v5 _" m2 y2 E% e
8 U8 o3 `/ ?3 P( Y/ ]9 w% O
[27:26]=008 L9 O$ |1 @8 @* i' [ J2 p( ]
( N' m* q* ^8 s* F
L[25]=1,代表op2是一个立即数) Q* [) c( n: v# X# C' z m
; X. J5 r7 L8 v
OpCode[24:21]=1101) a. h) s% u8 g* a6 S
- B- ]3 B; f- ?, o
S[20]=0
1 N1 V$ d$ _, W( q! r
9 u# c2 S+ q) l0 Q8 ~2 D5 N! @Rn[19:16]=0000
3 m% c3 T6 y* l3 F
+ m3 l; ?& i9 Y7 GRd[15:12]=0011,R3
) g. F4 G ^& {, l# X9 o8 q( m9 L
4 K; d1 h! V8 v3 Y( WOp2[11:8]=0100,右移4 * 2位* B4 W5 l! c. s# Y) ?, Y+ }& H1 c3 W
# _" u, V8 G3 m5 m$ t. x- C
Op2[7:0]=0101 0110,8位立即数,0x56
- ]6 g" y! i" J! m6 Q, P0 H( n) v H' S; e# L2 T6 x1 X
i' c2 g# z, K
6 p! \# u+ ?$ l7 s1 U) ]' L ]9 o
首先要将0x56扩展成32位的无符号数,0x00000056,然后循环右移8位,就得到了0x560000004 j6 G$ ]3 t6 {. V8 p7 U9 ~
- p |' ]: V9 q, ]- D- S9 b
2、mov r3, #0x56000014
, C' r( Z- O9 e7 V( c7 }
& L! D9 `; c5 }& @0x56000014是无法通过移位来得到的,这时汇编器会报错,C语言编写的程序,编译器会这样来处理:, Z1 ^, u+ A' p7 Q9 \; j5 [, V
6 I$ ?. g9 }) a; D3 Y/ [
mov r3, #0x56000000, ]% t6 F- {. b0 g
- f2 c! ^* I& F5 K! badd r3, r3, #0x14/ s; }9 }1 ]( n) k
: y! ]6 }5 E4 O$ Q* v$ K- v+ r转载End
|7 g0 c$ [) i% g1 C" _. B
+ m" Z$ z7 y2 u5 L- h. y明白了这个,也就可以理解为啥会有下面的写法:. H7 G0 l' c' |' b% u
#define INT_CTL_BASE 0x4A000000: M1 E8 o3 x) e& G. r
#define oINTMSK 0x08
6 p. b& _' v5 @- @" w#define oINTSUBMSK 0x1C
! e: r5 r! v% d9 W
5 A) e& F& ^% Z. y. d mov r1, #INT_CTL_BASE
; N3 e1 ^1 s+ `$ j mov r2, #0xffffffff7 i+ j; o4 ]2 ^- C& A7 \' L
str r2, [r1, #oINTMSK]
$ y' u0 u2 N/ k& L ldr r2, =0x7ff* M" C8 Q; R z( [
str r2, [r1, #oINTSUBMSK]! f9 U$ M- k' h1 ]0 X7 R. W
因为0x4A000008和0x4A00001C不能通过循环右移偶数个位来得到 |
|