版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
3 z O6 D' M4 N4 x看优龙FS2410(s3c2410)的bootloader: vivi, 思考摸索了有段时间的问题,代码如何从cpu上的sram中跳到SDRAM中的,从而引发了一连串的问题,此文的目的就是问题之一。
. Q/ W* n# L* D代码里会看到如下的指令:
: g9 h* P+ b7 M% }2 f6 xmov r1, #0x53000000: |) _ \6 o) H- I- a1 N7 y; T: i
而我们知道arm指令是4字节长,上面这个指令光立即数就已经4个字节了,所以,汇编器如何把这条汇编语句变成二进制指令的呢?2 B+ o% {8 K# B v: G/ o8 V
网络上答案很多,如下,不过原文有点小错误,已经高亮纠正
! Y- q( w" A8 v& M( K4 g# S. h; Y) L& p
" N6 c+ q. A+ ], P原文戳我
; P9 t3 t; R+ \( R转载Begin:
- c7 V a9 } cARM中的MOV指令格式是这样的0 K6 X( W* z' g3 F! z+ R+ Z
8 j# a e4 t; A& y/ O# `4 v3 Y/ `) k* L k
1 x2 m8 c% ^" G3 Q0 T6 w6 J
op2是占了12位,其中bit11-bit8是移位数(rotate),bit7-0是一个8位的立即数(imm),MOV Rn, op2,执行之后,Rn=op2 >> (rotate * 2),这里的移位是循环右移,这就决定了MOV指令不是所有的立即数都能表示的,以下是几个例子:
" l" G, e9 X, ^6 j' G' I' u5 C, T8 u
2 X2 W& w: V. k) \7 a! m- a; k: H, J- S0 v' `/ G
1、mov r3, #0x56000000& J8 _& Y7 R9 X I: Q5 [/ x2 u
0 J& @0 g: Y1 E/ @6 O5 F6 X; _虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码e3a03456,展开成二进制,对照下格式
# ~; Q1 C! S- r' q2 N3 X) c& T- O! y& E$ G% n
1110 0011 1010 0000 0011 0100 0101 01102 J8 s4 `+ j; N/ L0 l
7 h8 z" S6 A! \& @
cond[31:28]=11102 J! M3 q% `9 `# G6 l6 u# [; k: x
7 B$ V3 T9 g# W. [" q[27:26]=00
7 A# [2 Z7 I+ M3 q0 @1 u0 L8 y+ O6 t% R
L[25]=1,代表op2是一个立即数0 n$ E3 k i2 d& K6 U. H
" P: V! Z1 {8 B* ~; iOpCode[24:21]=1101
; V- m* ~: ~4 Z
7 m' `$ I+ q& i* oS[20]=0& c6 F1 ^3 s U& o: r
y1 X- G: {$ i9 t& HRn[19:16]=00001 U* |8 A- w$ _& v, n4 L0 H
" Q" V$ {5 H5 M* D" b4 v0 d5 _ kRd[15:12]=0011,R3
; D: w9 p' l, U k
9 T4 `; h; X+ e. Z* ^: ?% qOp2[11:8]=0100,右移4 * 2位& m6 @( F1 i3 p/ F$ [, ^0 N
- M/ j/ }) }( n$ m5 ~, T# DOp2[7:0]=0101 0110,8位立即数,0x56: o: p( X: w" Z0 F+ _
& n$ ~7 Q9 L, G. j ' V# w' K. y* V# ^7 Z
+ N1 C2 c' i1 M1 Q7 _
首先要将0x56扩展成32位的无符号数,0x00000056,然后循环右移8位,就得到了0x560000005 d2 O4 C6 U( Z4 Z! V' R
# f5 I. r( A4 e B
2、mov r3, #0x56000014, ?% f9 j' z* [
* a" `& q- {: v+ L8 Y6 p% w$ j0x56000014是无法通过移位来得到的,这时汇编器会报错,C语言编写的程序,编译器会这样来处理:
4 L+ n4 s8 b2 t3 p$ h4 A' h; K# ~5 f5 B
mov r3, #0x56000000
' h) d( e5 m: J* {* V
' U# d" V( F$ F# F8 @( R; wadd r3, r3, #0x14
" g: I$ g- ] S' K9 \
$ t! }8 }( _1 a' s& T7 E3 W转载End; Y, a7 X. I4 z% K
& W7 H3 q( I' t$ d
明白了这个,也就可以理解为啥会有下面的写法:# W, R ^8 L# m% V9 J* N/ z! V
#define INT_CTL_BASE 0x4A000000
; \8 l* v7 _! Y0 ^+ g1 u. @/ F" X5 F#define oINTMSK 0x08
2 E C2 B y# _% i' O+ l2 w, X#define oINTSUBMSK 0x1C
* O% Y) A8 c4 n+ I h. _
" f9 R7 \7 k3 K+ J mov r1, #INT_CTL_BASE' A; }# a% M+ |& {( ~
mov r2, #0xffffffff
1 Q9 s" P- i) H1 Y4 V+ d# ?1 ] str r2, [r1, #oINTMSK]
& q; N. G; C8 X' m8 ~& x ldr r2, =0x7ff
+ T' W ~0 P+ {, U: e str r2, [r1, #oINTSUBMSK]8 L) E) _; h% |& c% f0 J2 W$ l
因为0x4A000008和0x4A00001C不能通过循环右移偶数个位来得到 |
|