版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
* Y. P2 S& ?: R- k. O" M% Z看优龙FS2410(s3c2410)的bootloader: vivi, 思考摸索了有段时间的问题,代码如何从cpu上的sram中跳到SDRAM中的,从而引发了一连串的问题,此文的目的就是问题之一。
+ L" S# P" u3 }4 |$ N代码里会看到如下的指令:
- A8 `+ b* G* ^, q/ U$ t! }& Q4 kmov r1, #0x53000000
" t0 I! p4 c2 u0 n% J而我们知道arm指令是4字节长,上面这个指令光立即数就已经4个字节了,所以,汇编器如何把这条汇编语句变成二进制指令的呢?3 H5 A1 r( ] G* b! V' D& X) ~
网络上答案很多,如下,不过原文有点小错误,已经高亮纠正
( _1 \% Z" L+ ]' I) h8 v1 D* o/ O1 ]) T$ q
原文戳我8 }2 Y# e3 c$ H! f! m# s7 ]* `
转载Begin:
7 B8 p) }% M5 V2 _& qARM中的MOV指令格式是这样的
. I- l5 B H2 ]3 b! }3 F- K# }- p4 u
4 ~! j" s: ~# s8 I4 W
: `5 y7 \; m$ O5 q, i' u8 M! L d3 j" F6 ~: F
op2是占了12位,其中bit11-bit8是移位数(rotate),bit7-0是一个8位的立即数(imm),MOV Rn, op2,执行之后,Rn=op2 >> (rotate * 2),这里的移位是循环右移,这就决定了MOV指令不是所有的立即数都能表示的,以下是几个例子:
! l0 r; t- G3 r" {$ \' ]5 `9 D+ }
( h. X/ d# }& `7 |4 g. w
3 q! ?5 w' a: G, X
' x& p: w. A5 `1、mov r3, #0x56000000% ~% v% i1 x" I
5 I8 F! M+ m4 B6 Z2 o虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码e3a03456,展开成二进制,对照下格式
3 U! S: F7 G- @! G0 Y, ~, y5 I! t, h7 U9 ^6 v9 ?' F6 c; j
1110 0011 1010 0000 0011 0100 0101 0110# C( D0 v i. k: q9 ^' q
% E% A) M: g1 m) I7 |6 K! j
cond[31:28]=1110
- }0 E1 T n0 a) i7 G+ {
3 S+ f4 V+ T x, l9 \2 e8 i2 N[27:26]=00
1 W7 |9 T" R w9 z. ]+ m- ^
. I' S' K3 e$ m8 M, m# J. lL[25]=1,代表op2是一个立即数
U' J% g I g% y! X; ^
9 W+ u( |( C8 @8 \1 ?OpCode[24:21]=1101/ G3 V! P; v! }: J
& L8 m d" U) N/ m M, _
S[20]=0
. [, K& B5 ?) W* U3 p0 }. |0 ~4 {1 S
Rn[19:16]=00002 r5 D; ?: `! I% U5 V3 y+ Z
$ e5 a4 ~2 P+ a: S1 I; L% U
Rd[15:12]=0011,R33 q# o( _& C" E) a
7 K4 `. Y+ A o- n1 P
Op2[11:8]=0100,右移4 * 2位
4 H6 C1 M" s1 q1 }* J. P# K" F1 m% M& _
Op2[7:0]=0101 0110,8位立即数,0x563 y/ v* ~$ _% }
7 A/ N6 @! s3 N" \ ! u4 _ C0 s7 \+ L( i$ p
8 X) s, F$ [' d0 s- }首先要将0x56扩展成32位的无符号数,0x00000056,然后循环右移8位,就得到了0x56000000+ v! @* U( S! w0 q$ f$ M( Z3 T
3 E+ U* ~: U' w' J" B2 u
2、mov r3, #0x56000014
4 |; p2 W# l3 e/ k6 |/ d
/ Q B2 ]0 G2 }) [. l4 k* o4 J0x56000014是无法通过移位来得到的,这时汇编器会报错,C语言编写的程序,编译器会这样来处理:
+ F9 ]9 k' J( ]& u3 O5 W
, B' B0 ^0 z' D ]* P1 Cmov r3, #0x56000000
5 L2 O U0 I) [) e5 R3 s1 `- _- X( o, ]7 k/ a
add r3, r3, #0x14
9 s8 H0 O4 h% G) P' w D
% W& u% E0 a3 ?- E- `! i转载End
" o* ~! k* N+ o' q) b# X P' W0 x5 c7 ?8 b& M+ s7 |: `
明白了这个,也就可以理解为啥会有下面的写法:
# L8 C% H/ D+ X; p) N8 G$ T#define INT_CTL_BASE 0x4A000000
2 Z! d7 V9 J5 t& b. t* f$ A5 T#define oINTMSK 0x08
+ b8 s1 K& I! q* ]5 l#define oINTSUBMSK 0x1C
+ I- D2 m0 }7 O! X, }& L4 a q" o( \9 }% o: _* W; H; G
mov r1, #INT_CTL_BASE
7 W7 M0 O, y3 S! K# I; x: m2 u) Z mov r2, #0xffffffff
1 d# a! u) q' f( P str r2, [r1, #oINTMSK]
4 ^4 w. t6 _" q3 x' h# q% A ldr r2, =0x7ff6 v$ j% W2 U: T- p1 L+ ]6 }" h
str r2, [r1, #oINTSUBMSK]( U' T2 D1 y8 c
因为0x4A000008和0x4A00001C不能通过循环右移偶数个位来得到 |
|