ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

顯示具有 GCC 標籤的文章。 顯示所有文章
顯示具有 GCC 標籤的文章。 顯示所有文章

2011年9月1日 星期四

variable argument list

就是像 printf 一樣的可變個數的參數列。
在 wikipedia 裡說明得很清楚。
printf(const char *fmt,...)
後面的三個 ... 就代表參數個數可變。

可變參數是由 compiler 實做的,在C99 後引入 _VA_ARGS_ 這個 MACRO,用來代表這個功能。
http://en.wikipedia.org/wiki/Variadic_macro

實際implement 這類function 時,利用 va_start,  va_arg, va_end 依序取出參數列內的參數。

但是要作一個 var agumet 的 wrapper function 就麻煩了。
所以 variable argument 的 function 都實做兩個版本:
printf ---> vprintf
sprintf --> vsprintf.

一個是 直接使用 var argument 作為 interface,一個用 va_start 取出的 argument array pointer 作為參數。
所以要作一個 wrapper function 時,就要用 va_start( ) 取出 argument array pointer,再呼叫 v 字頭的 function..
void myprintf(const char *fmt,...) { va_list ap; va_start(ap,fmt); vprintf(fmt,ap); va_end(ap); } --- 用 vprintf,不是 printf。

2010年10月25日 星期一

myhello - native shell runnable program in android-linux

會這樣寫是因為這是在 shell run 的程式,沒有用 Dalvik. 是要看看 android linux 的 bionic , share library 用偷懶的方法,拿 system/extra/sound 來參考 (copy)
  • 在 system/extra 下 create "myhello" folder
  • copy sound 的 Android.mk 過來
  • 修改 Android.mk
  • mm
build log: make: Entering directory `/home/checko/myandroid8.1' target thumb C: myhello <= system/extras/myhello/myhello.c target Executable: myhello (out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/LINKED/myhello) target Non-prelinked: myhello (out/target/product/myBBG/symbols/system/bin/myhello) target Strip: myhello (out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello) Install: out/target/product/myBBG/system/bin/myhello Copy: out/target/product/myBBG/system/etc/apns-conf.xml make: Leaving directory `/home/checko/myandroid8.1' 在 croot (android project root),用 make showcommands myhello 的 log: build/core/copy_headers.mk:15: warning: overriding commands for target `out/target/product/myBBG/obj/include/libpv/getactualaacconfig.h' build/core/copy_headers.mk:15: warning: ignoring old commands for target `out/target/product/myBBG/obj/include/libpv/getactualaacconfig.h' /bin/bash: line 0: cd: sdk/layoutopt/app/src/resources: No such file or directory No private recovery resources for TARGET_DEVICE myBBG target thumb C: myhello <= system/extras/myhello/myhello.c prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-gcc -I system/core/include -I hardware/libhardware/include -I hardware/libhardware_legacy/include -I hardware/ril/include -I dalvik/libnativehelper/include -I frameworks/base/include -I frameworks/base/opengl/include -I external/skia/include -I out/target/product/myBBG/obj/include -I bionic/libc/arch-arm/include -I bionic/libc/include -I bionic/libstdc++/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -I bionic/libm/include -I bionic/libm/include/arch/arm -I bionic/libthread_db/include -I system/extras/myhello -I out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates -I out/target/product/myBBG/obj/STATIC_LIBRARIES/libwebcore_intermediates -c -fno-exceptions -Wno-multichar -msoft-float -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -march=armv5te -mtune=xscale -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -I system/core/include/arch/linux-arm/ -mthumb-interwork -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -DSK_RELEASE -DNDEBUG -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -MD -o out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello.o system/extras/myhello/myhello.c Install: out/host/linux-x86/bin/apriori out/host/linux-x86/bin/acp -fpt out/host/linux-x86/obj/EXECUTABLES/apriori_intermediates/apriori out/host/linux-x86/bin/apriori Install: out/host/linux-x86/bin/soslim out/host/linux-x86/bin/acp -fpt out/host/linux-x86/obj/EXECUTABLES/soslim_intermediates/soslim out/host/linux-x86/bin/soslim target Executable: myhello (out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/LINKED/myhello) prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-g++ -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/LINKED/myhello -Lout/target/product/myBBG/obj/lib -Wl,-rpath-link=out/target/product/myBBG/obj/lib -lc -lstdc++ -lm out/target/product/myBBG/obj/lib/crtbegin_dynamic.o out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello.o -Wl,--no-undefined /home/checko/myandroid8.1/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/interwork/libgcc.a out/target/product/myBBG/obj/lib/crtend_android.o target Non-prelinked: myhello (out/target/product/myBBG/symbols/system/bin/myhello) out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/LINKED/myhello out/target/product/myBBG/symbols/system/bin/myhello target Strip: myhello (out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello) out/host/linux-x86/bin/soslim --strip --shady --quiet out/target/product/myBBG/symbols/system/bin/myhello --outfile out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello Install: out/target/product/myBBG/system/lib/libdl.so out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/lib/libdl.so out/target/product/myBBG/system/lib/libdl.so Install: out/target/product/myBBG/system/lib/libc.so out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/lib/libc.so out/target/product/myBBG/system/lib/libc.so Install: out/target/product/myBBG/system/lib/libstdc++.so out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/lib/libstdc++.so out/target/product/myBBG/system/lib/libstdc++.so Install: out/target/product/myBBG/system/lib/libm.so out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/lib/libm.so out/target/product/myBBG/system/lib/libm.so Install: out/target/product/myBBG/system/bin/myhello out/host/linux-x86/bin/acp -fpt out/target/product/myBBG/obj/EXECUTABLES/myhello_intermediates/myhello out/target/product/myBBG/system/bin/myhello 這樣build 出來的 myhello 會被 install 在 system/bin 中,boot 後直接 invoke 就可以執行。 啟動 strace myhello 的內容: strace myhello execve("/system/bin/myhello", ["myhello"], [/* 19 vars */]) = 0 syscall_983045(0xb0017900, 0xbed6dbb4, 0, 0x847c, 0xb000f448, 0xbed6dbb0, 0x8, 0xf0005, 0, 0, 0, 0, 0, 0xbed6db58, 0xb000194b, 0xb000228c, 0x80000010, 0xb0017900, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 getpid() = 2109 sigaction(SIGILL, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGABRT, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGBUS, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGFPE, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGSEGV, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGSTKFLT, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGPIPE, {0xb0001d45, [], SA_RESTART}, {SIG_DFL}, 0) = 0 getuid32() = 0 geteuid32() = 0 getgid32() = 0 getegid32() = 0 stat64("/system/lib/libc.so", {st_mode=S_IFREG|0644, st_size=239972, ...}) = 0 open("/system/lib/libc.so", O_RDONLY|O_LARGEFILE) = 3 lseek(3, 0, SEEK_SET) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0 \250\0\000"..., 4096) = 4096 lseek(3, -8, SEEK_END) = 239964 read(3, "\0\0\340\257PRE ", 8) = 8 mmap2(0xafe00000, 286720, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xafe00000 mmap2(0xafe00000, 228532, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0xafe00000 mprotect(0xafe00000, 229376, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 mmap2(0xafe38000, 8596, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x38) = 0xafe38000 mmap2(0xafe3b000, 42160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xafe3b000 close(3) = 0 mprotect(0xafe00000, 229376, PROT_READ|PROT_EXEC) = 0 getuid32() = 0 geteuid32() = 0 getgid32() = 0 getegid32() = 0 gettid() = 2109 syscall_983045(0xafe42ad4, 0xafe42a98, 0, 0x40, 0xafe38e08, 0xbed6dbb0, 0xbed6da58, 0xf0005, 0, 0, 0, 0, 0, 0xbed6da48, 0xafe1f721, 0xafe0d89c, 0x60000010, 0xafe42ad4, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 mmap2(NULL, 32768, PROT_READ, MAP_SHARED, 9, 0) = 0x40000000 open("/dev/urandom", O_RDONLY|O_LARGEFILE) = 3 read(3, "\223\31\234=", 4) = 4 close(3) = 0 stat64("/system/lib/libstdc++.so", {st_mode=S_IFREG|0644, st_size=5268, ...}) = 0 open("/system/lib/libstdc++.so", O_RDONLY|O_LARGEFILE) = 3 lseek(3, 0, SEEK_SET) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0X\10\0\000"..., 4096) = 4096 lseek(3, -8, SEEK_END) = 5260 read(3, "\0\0\320\257PRE ", 8) = 8 mmap2(0xafd00000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xafd00000 mmap2(0xafd00000, 2848, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0xafd00000 mprotect(0xafd00000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 mmap2(0xafd01000, 232, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1) = 0xafd01000 close(3) = 0 mprotect(0xafd00000, 4096, PROT_READ|PROT_EXEC) = 0 getuid32() = 0 geteuid32() = 0 getgid32() = 0 getegid32() = 0 stat64("/system/lib/libm.so", {st_mode=S_IFREG|0644, st_size=132116, ...}) = 0 open("/system/lib/libm.so", O_RDONLY|O_LARGEFILE) = 3 lseek(3, 0, SEEK_SET) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0@ \0\000"..., 4096) = 4096 lseek(3, -8, SEEK_END) = 132108 read(3, "\0\0\300\257PRE ", 8) = 8 mmap2(0xafc00000, 135168, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xafc00000 mmap2(0xafc00000, 129828, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0xafc00000 mprotect(0xafc00000, 131072, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 mmap2(0xafc20000, 280, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x20) = 0xafc20000 close(3) = 0 mprotect(0xafc00000, 131072, PROT_READ|PROT_EXEC) = 0 getuid32() = 0 geteuid32() = 0 getgid32() = 0 getegid32() = 0 mprotect(0x8000, 4096, PROT_READ|PROT_EXEC) = 0 getuid32() = 0 geteuid32() = 0 getgid32() = 0 getegid32() = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000 mprotect(0x40008000, 4096, PROT_READ) = 0 fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(207, 16), ...}) = 0 brk(0) = 0xa000 brk(0xa000) = 0xa000 brk(0xc000) = 0xc000 mprotect(0x40008000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x40008000, 4096, PROT_READ) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 write(1, "Hello Bionic\n", 13Hello Bionic ) = 13 mprotect(0x40008000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x40008000, 4096, PROT_READ) = 0 munmap(0x40008000, 4096) = 0 exit_group(0) = ? Process 2109 detached 所以確認 share library path 是 OK 的 :(

2010年9月24日 星期五

build ffmpeg with --disable-optimizations

因為要用 gdb run,所以用 --disable-optimizations 的 option。 結果會出現: In file included from /home/ffmpeg/ffmpeg/libavcodec/x86/dsputil_mmx.c:31: /home/ffmpeg/ffmpeg/libavcodec/x86/dsputil_mmx.h: In function ‘transpose4x4’: /home/ffmpeg/ffmpeg/libavcodec/x86/dsputil_mmx.h:98: error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’ /home/ffmpeg/ffmpeg/libavcodec/x86/dsputil_mmx.h:98: error: ‘asm’ operand has impossible constraints make: *** [libavcodec/x86/dsputil_mmx.o] Error 1 google 的結果說是 gcc 的問題,好像是 ebp 可不可以拿來用的問題。 但是 apply 所有 google 到的 solution 都沒有效。 所以,只好... configure --disable-mmx --disable-mmx2 --disable-optimizations --disable-stripping 這樣就 OK 了... 很糟糕又丟臉的方法,但是主要是要 trace transport stream 的 decoding process,所以 assembly optimize 部份可以先略過...

2010年2月25日 星期四

kernel building error on gcc 4.3 - __umoddi3()

真誇張:
busybox -- qemu boot with preload kernel -- ref jserv's tutorial -- build kernel fail 
-- workaround on CFLAG -- GCC 4.3 problem -- GCC 4.3 optimize functions -- example 
test code

繞了好大一圈,已經離 busybox 很遠了..
最後是 這一篇 王聰 先生的blog : __umoddi3()的問題 有比較清楚的說明: (copy 一下,以免消失.. 對不起)

以下 copy 自 王聰 先生的 blog 文章:
===========================================================
在編譯內核時有人遇到下面這個問題:

kernel/built-in.o: In function `getnstimeofday':
(.text+0xb6ae): undefined reference to `__umoddi3'
kernel/built-in.o: In function `getnstimeofday':
(.text+0xb6ce): undefined reference to `__udivdi3'

這個問題可以在用戶空間重現,不過不是很容易,我實驗了一下,在i386上,並不是所有的64位整數操作都會被轉化成
調用__umoddi3,gcc bugzilla上有演示程序,如下:
PLAIN TEXT
C:

  1.#define NSEC_PER_SEC  1000000000UL     
  2.int rmg(void);
  3.
  4.int main(void)
  5.{
  6.  /* int sec; */
  7.  return rmg();
  8.}
  9.
 10.int rmg(void)
 11.{
 12.  static unsigned long long nsec = 0;
 13.  static int sec = 0;
 14.  while (sec <1 ) {
 15.    nsec++;
 16.    while (__builtin_expect(nsec>= NSEC_PER_SEC, 0)) {
 17.    nsec -= NSEC_PER_SEC;
 18.    ++sec;
 19.    }
 20.  } 
 21.  return sec;
 22.}

這樣編譯它:% gcc -nostdlib -O2 -o umoddi3 umoddi3.c,就會得到:

/tmp/ccycM684.o: In function `rmg':
umoddi3.c:(.text+0x87): undefined reference to `__udivdi3'
collect2: ld returned 1 exit status

問題重現了。這裡的問題是,對於nsec來說,內層的循環其實等價於求模運算,gcc在優化時發現了這一點,而且硬件
本身也不支持對64位整數直接進行算術運算,所以gcc會把這一步優化成調用內部函數__udivdi3()和
__umoddi3(),這兩個函數在libgcc中(見gcc源代碼 gcc/libgcc2.c),libgcc默認和libc一樣是要被加載
的,但如果我們加了-nostdlib(Linux內核是更好的例子),這個問題就會出現了。

知道原因了,怎麼解決?網上有兩種方法,一種是像這個補丁那樣,在循環中插入下面這條內聯彙編:

asm("" : "+r"(ns));

這句是告訴gcc把ns這個變量放到寄存器中,並且既有讀操作也有寫操作,所以後面再用它時必須重新讀取,這樣就消
除了上面的優化。

另一種解決方法是添加新的編譯選項:-fno-tree-scev-cprop,這個選項似乎沒有文檔,至少我沒找到。說說它的
大體意思。scev 應該是SCalar EVolutions,什麼意思不知道。:( cprop應該是Copy PROPagation,這個應
該很容易理解,就是賦值的傳播,比如:

i = 10;
a = i;
b = i;

其實就是:

a = 10;
b = 10;

可見,編譯優化是門大學問,寫個編譯器絲毫不比寫個內核容易。:-P
============王聰先生的文章copy到此==============

2009年9月8日 星期二

GCC - library link order

http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html 2.7.1 Link order of libraries linker 尋找 extern function 的搜尋順序是 follow command 的指示,依次從左到右。 所以在指定 -l 外部 library 時,順序很重要:
$ gcc -Wall calc.c -lm -o calc   (correct order)
With some linkers the opposite ordering (placing the -lm option before the file which uses it) would result in an error,
$ cc -Wall -lm calc.c -o calc    (incorrect order)
main.o: In function `main':
main.o(.text+0xf): undefined reference to `sqrt'
因為command 的order,calc.c 後面沒有寫明任何 library,calc.c 使用到的sqrt 雖然有定義在 libm ,但是command 列在calc.c 之前,所以 linker 找不到。 When several libraries are being used, the same convention should be followed for the libraries themselves. A library which calls an external function defined in another library should appear before the library containing the function. 例如, data.c 使用到 linear programming library : library,library 又使用到 math library : libm。所以正確的linking order 是:
$ gcc -Wall data.c -lglpk -lm
since the object files in ‘libglpk.a’ use functions defined in ‘libm.a’. 目前大多數的 linker 都會(重複?)搜尋所有指定的 external library,所以 linking order 在目前似乎沒那麼重要。 但是當你在build 時遇到 undefined external,而你又確定該 symbol 是有定義的,或許試試是不是 linking order 的問題。
還有另一個問題是重複的function,如果一個function 在兩個 external libary 都有定義,linker 會採用 linking order 在前面的那個 libary (依照找到的順序)。

2009年9月2日 星期三

msys, mingw

follow 這個link 安裝 msys + mingw 時要知道的事:
msys 和 mingw 是兩個不一樣的東西。
msys 和 mingw 都有自己的 file hierarchy (bin, usr, lib,...)。
所以,當自己 download msys, mingw 的 package 下來安裝 (其實也就是解開-copy 覆蓋)時。
  • 屬於 msys 的 package,就要 copy 到 msys 的 folder root。
  • 屬於 mingw 的 package,就要 copy 到 mingw 的 folder root。
link 中,build ffplay 安裝 SDL lib 時,有一個地方好像寫錯:
Copy all the files from the lib folder to C:\msys\mingw\lib\.
Copy the SDL folder from the include folder to C:\msys\mingw\include\.
Copy all the files from the bin folder to C:\msys\mingw\bin\.
其中的 path 應該是
C:\mingw\lib\.
C:\mingw\include\.
C:\mingw\bin\.
因為follow default setting 的話, minGW 是 install 在 c:\mingw。
而且mingw 比 msys 先安裝,要怎樣 install 到 msys 的 folder 中呢?
這一篇有圖文並茂的 msys, mingw的安裝教學 (我沒看 )

2009年6月30日 星期二

.gvfs permission denied

新買的hd要掛在/home/james下。 所以
$sudo rsync -av /home/james/ /home/tmp/
結果出現 error :
rsync: readlink_stat("/home/james/.gvfs") failed: Permission denied (13)
看一下這個 folder 的 permission 是 r_x,沒有w。 查一下,gvfs是新的 gnome vfs 架構,使用gio library。 會在login x 的 user home dirctory 下 mount .gvfs folder 到gvfs。 所以..先logout,login 成其他人, umount /home/james/.gvfs 之後,就可以 rsync ..

2009年2月16日 星期一

ARM GCC Inline Assembler

翻譯這一篇 : arm gcc inline assembler cookbok 但是這一篇(GCC-inline assembly Howto)說得比較仔細。 GCC 的 inline assembly 基本格式是:
  asm(code : output operand list : input operand list : clobber list);
也就是一堆用 ':'分開的字串。 其中 'code' 的部份要存取 output operand list , input operand 的內容,是用 % 符號:
 %0 代表存取 output operand
%1 代表存去 input operand
最後的'clobber' 是要告訴 compiler 有哪些 register 被這段 assembly code 修改了。
為了防止 compiler 把這一段 inline assembly code optimize 掉,通常都會加上 volatilr:
 asm voltaile("mov %0, ror #01" : "-r" (result) : "r" (value));
這段 inline assembly,如果之後的部份都沒有資料,就可以不寫,舉例來說:
 asm volatile("mov r0, r0");
這只是用來delay的code,沒有input, output,也沒有 register 會被修改,所以後面的 部份都不用寫。 但是如果有資料一定要寫,他的前面部份就不可以省略,舉例來說:
 asm volatile("" : : : "memory");
這段inline assembly 不包含任何 code,只是告訴 compiler memory 有可能會被修改。 一般為了好看,建議將一堆 assembly 寫成這樣:
 asm volatile(
"mov r0,r0\n\t"
"mov r0,r0\n\t"
"mov r0,r0\n\t"
);
也就是說,分行寫,但是要記得加上 "\n\t" - 這是要讓 compiler listing 時,比較好看。 Input Output Operand 這兩個區域是要告訴 compiler operand 的資料,利用以下 "Constraint" 來通知: Operand Register 的類型:
  • f : 是floating point register (有些 cpu 有專屬的 floating point register)
  • I : 立即定址 immediate operands
  • J : Indexing constants
  • K : negative value in rhs
  • L: negative value in rhs
  • M : for shift
  • r : General registers -- ARM 一般用這個
Operand Register 的 in/out:
  • = : Write-only (通常所有的 output operand 都會加這個符號)
  • + : Read-Write (inline assemnly 不支援這個符號)
  • & : Output only - 這個register 只做 output 使用
Output Operand 一定要是 Write-Only。 Input Operand 一定要是 Read-Only。 但是如果要把 input operand 修改後,作為 output operand 的話,要怎麼辦呢? inline assembly 又不支援 '+' 符號.. 用"數字" 來告訴 complier 這一個 operand 共用哪一個 operand,例如:
asm volatile("mov %0, %0, ror #1" : "=r" (value) : "0" (value));
這個 code 是將'value" right shit 1 bit。 但是用同一個 register 來作就可以。 input operand 用 "0" 告訴 compiler ,使用 第0個operand (就是 output operand)。 所以 input, output 都會用同一個 register (mov %0, %0..)。 Clobbers 把被修改的部份寫在這
asm volatile(
"amsd   r3, %1, #3  \n\t"
"eor    %0, %0, r3  \n\t"
"addne  %0, #4"
: "=r" (len)
: "0" (len)
: "cc","r3"
);
例子使用了 r3 作scratch register,所以做完這段 code 後,r3的值會被修改,以在clobber的區域要列出 "r3"。 另外,作邏輯運算後,status 區域也會修改,所以要把"cc"也列上。 還有另一個例子:
asm volatile(
"ldr  %0, [%1]  \n\t"
"str  %2, [%1, #4]  \n\t"
: "=&r" (rdv)
: "r" (&table), "r" (wdv)
: "memory"
);
這一段code會update table 的內容,所以要在....
有一點沒寫到,就是 c variable name 都寫在 operand 後面,用括號( )括起來..
在 "Assembler Instruction with C expression operand" ,範例:
asm ("fsinx %[angle],%[output]"
   : [output] "=f" (result)
   : [angle] "f" (angle));
在operand 前可以用 [name] 寫出''將會用這'name'名字稱呼''。 然後在 code 區域就可以直接用 %[name] 來引用
大概可以這樣說: assembly code 中,要引用 C 宣告的部份,就要寫在 operand (in/out) 欄位,並且寫號 constrain. 然後用 %0, %1...來使用。 如果是直接存取 register,就直接用 r1, r2, r3... 但是要記得寫在 clobber 欄位。
ref:

標籤

網誌存檔