1)下載下傳必要的軟體,我是在VMWare上建的環境,需要準備好下面這些軟體
ARM-Linux的交叉平台編譯工具arm-elf-tools
<a href="http://www.uclinux.org/pub/uClinux/arm-elf-tools/">http://www.uclinux.org/pub/uClinux/arm-elf-tools/</a>
裡面都是rpm包,使用rpm指令安裝就可以了.
skyeye-1.2.5和skyeye-testsuite-1.2.5
<a href="http://gro.clinux.org/frs/?group_id=327">http://gro.clinux.org/frs/?group_id=327</a>
2)安裝skyeye
進入skyeye的解壓目錄後,執行下面的指令
#./configure
#./make
#./make install
3)安裝和運作testsuite
#bzip2 -d skyeye-testsuite-1.2.5.tar.bz2
#tar -xf skyeye-testsuite-1.2.5.tar
#cd skyeye-testsuite-1.2.5/linux/s3c2410/s3c2410x-2.6.14
#skyeye -e vmlinux
看到ARM Linux啟動了,就是運作成功了
上面的過程太順利了,我想利用skyeye運作了一下自己的ARM程式,觀察程式運作的效果。
是以開始了下面的步驟。
1)生成ARM elf可執行程式
我對彙編不是很熟,剛開始學,不想陷入彙程式設計式的泥潭裡。
是以這裡首先使用c作為開發語言。Sample程式如下:
test.c:
void _start()
{
int gint=-1;
int ret=-20;
ret=gint+ret;
}
注意上面的函數名必須是_start,這是arm-gcc認可的程式入口函數,就像c語言裡的main函數一樣。
然後使用arm-gcc進行編譯。
#export PATH=/opt/cross/arm/2.95.3-2.15/arm-cacko-linux-gnu/bin:$PATH
#gcc -S test.c
#as test2.s -o test.o
#ld test.o -o test
2)運作ARM elf可執行程式
編譯OK了,下面嘗試運作它吧!
首先要準備skyeye.conf配置檔案.你可以從一個Sample配置檔案稍微改改就可以了,比如Skyeye README中的.
這裡使用下面的簡單的配置檔案。
cpu: arm920t
mach: s3c2410x
# physical memory
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00800000
mem_bank: map=M, type=RW, addr=0xff7fffff, size=0x00800000
lcd: type=s3c2410x, mod=gtk
下面執行前面的test ARM 程式。
#skyeye -e test
Your elf file is little endian.
arch: arm
cpu info: armv4, arm920t, 41009200, ff00fff0, 2
mach info: name s3c2410x, mach_init addr 0x806bd90
uart_mod:0, desc_in:, desc_out:, converter:
SKYEYE: use arm920t mmu ops
start addr is set to 0x00008074 by exec file.
現在它已經運作完了,不過看不到結果.下面準備通過日志觀察結果.
在skyeye.conf配置檔案中追加下面一行,訓示Skyeye每次執行一條指令時,輸出CPU内部的各組寄存器的值。
log: logon=2, logfile=/tmp/sk1.log, start=0, end=100
現在再執行一遍剛才的程式,日志應該已經生成了.對照一下前面編譯時生成的彙程式設計式,和日志中記錄的
CPU寄存器的值的變化吧。
# cat test2.s
@ Generated by gcc 2.95.3 20010315 (release) for ARM/elf
.file "test2.c"
gcc2_compiled.:
.text
.align 2
.global _start
.type _start,function
_start:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, current_function_anonymous_args = 0
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
sub sp, sp, #8
mvn r3, #0
str r3, [fp, #-16]
mvn r3, #19
str r3, [fp, #-20]
ldr r3, [fp, #-20]
ldr r2, [fp, #-16]
add r3, r3, r2
.L2:
ldmea fp, {fp, sp, pc}
.Lfe1:
.size _start,.Lfe1-_start
.ident "GCC: (GNU) 2.95.3 20010315 (release)"
上面一共有13條指令,現在我們跟蹤一下這13條指令的執行情況
# head -14 /tmp/sk1.log
N 0 :p 8074,i e1a0c00d,R 0,c1,0,0,0,0,0,0,0,0,0,0,0,0,0,807c,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 1 :p 8078,i e92dd800,R 0,c1,0,0,0,0,0,0,0,0,0,0,0,0,0,8080,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 2 :p 807c,i e24cb004,R 0,c1,0,0,0,0,0,0,0,0,0,0,0,fffffff0,0,8084,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 3 :p 8080,i e24dd008,R 0,c1,0,0,0,0,0,0,0,0,0,fffffffc,0,fffffff0,0,8088,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 4 :p 8084,i e3e03000,R 0,c1,0,0,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,808c,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 5 :p 8088,i e50b3010,R 0,c1,0,ffffffff,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,8090,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 6 :p 808c,i e3e03013,R 0,c1,0,ffffffff,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,8094,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 7 :p 8090,i e50b3014,R 0,c1,0,ffffffec,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,8098,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 8 :p 8094,i e51b0014,R 0,c1,0,ffffffec,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,809c,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N 9 :p 8098,i e51b1010,R ffffffec,c1,0,ffffffec,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,80a0,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N a :p 809c,i eb000000,R ffffffec,ffffffff,0,ffffffec,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,0,80a4,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N b :p 80a4,i e1a0c00d,R ffffffec,ffffffff,0,ffffffec,0,0,0,0,0,0,0,fffffffc,0,ffffffe8,80a0,80ac,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N c :p 80a8,i e92ddbe0,R ffffffec,ffffffff,0,ffffffec,0,0,0,0,0,0,0,fffffffc,ffffffe8,ffffffe8,80a0,80b0,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
N d :p 80ac,i e24cb004,R ffffffec,ffffffff,0,ffffffec,0,0,0,0,0,0,0,fffffffc,ffffffe8,ffffffc4,80a0,80b4,C d3,S 0,0,0,0,0,0,0,M 13,B 3,E 0,I 0,P 0,T 0,L 0,D 0,
題外話:
做這個練習的時候我正在學習ARM系統,對其中的一些東西不太了解,現在通過上面方法終于搞清楚了。
1)ARM系統裡PC指向取指位址,而不是正在執行的指令的位址,由于流水線的原因,PC指向的是目前正在執行的指令的後面第2個指令。
同時我證明了彙編器在計算相對位址時已經考慮到這個問題。比如下面的語句。
loop:b loop
b跳轉到自己,彙編器産生的跳轉指令的偏移量是-2而不是0。
2)CPU的CZVN四個狀态位,根據對它們的描述,有幾位是關于有符号數的(VN),有的是關于無符号數的(C),但CPU如何區分有符号數操作和無符号數操作的呢?
作了試驗才明白,CPU是不做區分的,它按照一緻的方法對應。以加法操作為例
C:邏輯上是針對無符号數的,是以CPU假設操作就是無符号數.
N:邏輯上是針對有符号數的,是以CPU假設操作就是有符号數.
V:邏輯上是針對有符号數的,是以CPU假設操作就是有符号數.
另外,由于用于儲存有符号數的補碼的特點,使得不論是有符号數的加減和還是無符号數的加減,其産生的二進制資料都是一樣。