版主
主题
帖子
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
3 G" R% M* M' w. C" U% q看优龙FS2410(s3c2410)的bootloader: vivi, 思考摸索了有段时间的问题,代码如何从cpu上的sram中跳到SDRAM中的,从而引发了一连串的问题,此文的目的就是问题之一。
- n# H, H; n/ L; l' @3 K代码里会看到如下的指令:7 l8 P7 M; v$ \- v8 ~
mov r1, #0x53000000
! n* M6 U& d. w G* m' n% k9 i而我们知道ARM指令是4字节长,上面这个指令光立即数就已经4个字节了,所以,汇编器如何把这条汇编语句变成二进制指令的呢?# y4 H* p& U1 n, J+ f. n: M. q$ W
网络上答案很多,如下,不过原文有点小错误,已经高亮纠正
1 d# K g, Q# G8 z8 g5 x* d+ v3 a- A/ K; }' O" x3 U
原文戳我
! [. V+ b0 u# Z' f转载Begin:
4 s3 E8 T9 {. t* U0 F+ H- H3 U6 kARM中的MOV指令格式是这样的& {1 H( c5 ?+ C1 k1 F# K
0 L P0 G) @8 w a
o! w- X Y& b! m2 o0 k" i% m
: t; n, a; k' V% D/ o; s: J4 f/ S op2是占了12位,其中bit11-bit8是移位数(rotate),bit7-0是一个8位的立即数(imm),MOV Rn, op2,执行之后,Rn=op2 >> (rotate * 2),这里的移位是循环右移,这就决定了MOV指令不是所有的立即数都能表示的,以下是几个例子:
) y4 n* G( w ] Z" j& U/ \
' q4 y0 N8 T: y- g8 H Z) {+ o
9 a/ Z4 S1 ?3 }2 D6 @$ S8 E7 g6 Z% y# v! S: L( I! O$ h; A
1、mov r3, #0x56000000
1 B5 x6 B3 `9 d3 |" z
# M+ x/ }! X4 r. t; d虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码e3a03456,展开成二进制,对照下格式
+ K2 L& f8 Y, _ t/ D# a
& s+ ?$ Y7 K" f! z$ q2 J' s1110 0011 1010 0000 0011 0100 0101 01102 z; k9 S9 b* b& L
1 V/ v: R- ~3 j7 e( ucond[31:28]=1110
6 P/ E! m1 R6 V- ^; a% k3 M% p& X3 r4 R
[27:26]=001 q" h* `/ N/ J ]
}$ r& F7 v$ j7 ^L[25]=1,代表op2是一个立即数
6 h+ ^% Z s w8 y) O' P! J" ?! i7 n8 T
OpCode[24:21]=11010 [ g( V K5 V: Z! i% D
; e1 ]( l# w$ X% ^0 x
S[20]=04 Z+ d2 P( O9 u, T. k' R
- |7 Z Y5 r; l$ GRn[19:16]=0000
! |- H. G* }# n+ n% L0 @" `1 ?2 f- H
Rd[15:12]=0011,R3
' B0 o9 D( H% U
- C4 [7 M5 `' @8 NOp2[11:8]=0100,右移4 * 2位; f- |5 B j1 y" J
( q$ O& |) O/ m. A2 W' ^0 p+ [
Op2[7:0]=0101 0110,8位立即数,0x561 R. d$ C J1 m' ^5 G+ C; F! m( u
4 Z, v) z& Q, g* ~" X6 r
3 y* r- J% P* P1 d( q$ z5 W. \( e8 \5 l% q5 S4 j1 q
首先要将0x56扩展成32位的无符号数,0x00000056,然后循环右移8位,就得到了0x56000000
{1 S! t# g( q N7 C
3 U7 Z7 O6 Q8 t8 ^2、mov r3, #0x56000014. c7 w3 Q" k/ q' Q9 v/ i0 b
! o* b8 a# [* O
0x56000014是无法通过移位来得到的,这时汇编器会报错,C语言编写的程序,编译器会这样来处理:
+ `2 u7 O9 U# B% N' E6 I
# J' K' D/ x$ ^' h; Wmov r3, #0x56000000
2 a- q6 r/ {9 h4 J7 P3 ?2 u6 P
add r3, r3, #0x140 t1 j$ @) G, X6 h0 _ }
" y! F4 Z8 c* s- m2 t! p转载End
( y+ O& g; }- g/ d
5 x+ V- i7 \, L! E) z明白了这个,也就可以理解为啥会有下面的写法:$ \! F8 T/ \2 s/ l7 _' J
#define INT_CTL_BASE 0x4A000000
* s' {4 P' i6 c#define oINTMSK 0x08
: h& R5 J! ~0 X#define oINTSUBMSK 0x1C5 k8 F( j- v. n2 \2 F; P
* @- \7 S. w$ _8 N, J# \/ I7 U ? mov r1, #INT_CTL_BASE8 `: B" c2 \+ N# _( f2 Y2 Z
mov r2, #0xffffffff
7 H4 B. @+ ?% J& T$ ` str r2, [r1, #oINTMSK]
! q% x8 O. H' _5 u' U* ]) T5 X ldr r2, =0x7ff
! O7 ]" V8 S2 p6 i% s str r2, [r1, #oINTSUBMSK]
- `- l, h& h3 Z; t8 L因为0x4A000008和0x4A00001C不能通过循环右移偶数个位来得到 |
|