版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
5 F1 L" Q$ D. R0 [( P
看优龙FS2410(s3c2410)的bootloader: vivi, 思考摸索了有段时间的问题,代码如何从cpu上的sram中跳到SDRAM中的,从而引发了一连串的问题,此文的目的就是问题之一。
4 k) \2 H! J* u0 m6 q代码里会看到如下的指令:( |; M+ T( b e
mov r1, #0x53000000% o% [+ O+ s" X/ N3 [2 s
而我们知道ARM指令是4字节长,上面这个指令光立即数就已经4个字节了,所以,汇编器如何把这条汇编语句变成二进制指令的呢?6 N8 c" ]! z4 d+ _9 |6 P, R
网络上答案很多,如下,不过原文有点小错误,已经高亮纠正
: G0 g# A5 s& g0 ?, C: J# H' d* S6 @. M# o/ j4 ~- R
原文戳我
- ?* I5 `0 p+ s# E% F& F1 G" { y转载Begin:* W% M: g3 ?1 A$ R& _/ _. q
ARM中的MOV指令格式是这样的* \$ i$ I1 D- _! m) `: A: v1 z
, g' I. D: \( p
: G2 f2 X/ h7 s! v7 e9 b- ]6 ^; {1 a# B( U7 f$ Q. H6 a
op2是占了12位,其中bit11-bit8是移位数(rotate),bit7-0是一个8位的立即数(imm),MOV Rn, op2,执行之后,Rn=op2 >> (rotate * 2),这里的移位是循环右移,这就决定了MOV指令不是所有的立即数都能表示的,以下是几个例子:' J- e* `4 n$ t# Z) q3 d+ q
, \$ V, N' W1 y- k0 R& c
/ b% M G) `+ D0 h x* m# w& g) a* q" ]7 @/ k5 w
1、mov r3, #0x56000000, |/ _2 m3 }0 p/ w, |
, z, r6 t Y' J S2 ^ C0 G* i
虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码e3a03456,展开成二进制,对照下格式& o& t3 g" }6 }
2 `: V/ E3 S3 q3 O5 |# u1110 0011 1010 0000 0011 0100 0101 0110
j& {. t" J1 l8 D7 n( }6 {* t7 t3 \ u1 }
cond[31:28]=1110/ d% D+ S9 T# Y7 R! x/ w
- E5 p6 \2 ^0 D4 R
[27:26]=004 [' v4 n) [+ A2 {+ h: q
4 O& U; M( `+ GL[25]=1,代表op2是一个立即数; a1 [& ^) Q+ {1 g: @) v! F
) j _* f6 E/ ^6 BOpCode[24:21]=11014 E D, [9 M1 o4 R1 d
5 w% E q" o# i8 |5 e, s$ LS[20]=0( k! ?, S: y, Z
8 x. o9 A$ [6 C& g; E; DRn[19:16]=0000
" U0 n& s( E! o. c9 m' o& N
7 B" f- R" q7 H4 l3 Q9 DRd[15:12]=0011,R3, u8 W$ m. p$ h1 K$ p" b9 `
" q& k, y& V& u g7 ^8 ?
Op2[11:8]=0100,右移4 * 2位9 v5 M' j6 s! W; x. K
$ N" j+ P$ B+ e9 a3 T/ w7 C+ m
Op2[7:0]=0101 0110,8位立即数,0x56
9 O0 J- r; k/ Q) s; j% V0 d. N _, T- A
/ {& Q& C5 C0 v) _
- K: I: \* |) p$ |) I" x8 H! R2 ?5 e首先要将0x56扩展成32位的无符号数,0x00000056,然后循环右移8位,就得到了0x560000005 j% B. J; i) c2 b+ I. i% B$ q
7 c1 t2 I. {" Y# B
2、mov r3, #0x56000014
4 m) E: l% _+ v
9 f! M7 D/ S% ~( G1 ]0x56000014是无法通过移位来得到的,这时汇编器会报错,C语言编写的程序,编译器会这样来处理:$ Y, v2 ^) T# A- q$ w( D& u
9 x4 n; q$ j& V7 Y$ Q/ zmov r3, #0x56000000' h& `- j3 v& W! V9 I9 W! H
( [- p( u) n9 `( @5 v# Z6 gadd r3, r3, #0x14
1 [; Y+ f% |+ A9 P6 ]/ k1 B3 s" L" Z
转载End
+ d( O$ F) |( K4 h2 [( H' h7 O( ^5 v0 e3 `
明白了这个,也就可以理解为啥会有下面的写法:. o% R8 y2 ?. _- F# N
#define INT_CTL_BASE 0x4A000000" X" P, i" v+ [$ V( ~+ p8 m( e
#define oINTMSK 0x08
6 G8 u6 o0 w$ }) ^; D, X8 S f0 N#define oINTSUBMSK 0x1C
( M) C. }9 R7 o( T3 H8 A0 p* g; i; p7 E* y0 P% P: |; h
mov r1, #INT_CTL_BASE# a6 l0 M! @* L, [4 S: V
mov r2, #0xffffffff2 f+ c0 g ~" r0 \. @- a
str r2, [r1, #oINTMSK]
: |' ]7 Q% P- i+ p$ M8 y- c# E @ ldr r2, =0x7ff
1 {; h& A. v5 e str r2, [r1, #oINTSUBMSK]
, P4 g- ?- W, U6 Y8 O因为0x4A000008和0x4A00001C不能通过循环右移偶数个位来得到 |
|