ARM cortex-m3 assembly - 1
收錄於 : 關於Ameba的一百篇
Found one slide about cortex-M assembly language programming
http://www.slideshare.net/GonzaloSantiago/assembly-language-programming-arm-cortexm3-vincent-mahout
組合語言的相關資料很多. 這篇主要簡單介紹一下怎麼在 Arduino 下寫組合語言.
以 Ameba 為例 ( 其他板子也可以 )
組合語言, 其實就是直接寫 CPU 要做的指令. 因為 CPU 聽得懂的話和 人說的話不同.
所以得用所謂的組合語言來溝通. 所有這顆 CPU 懂得的指令, 就叫做指令集.
( 現在網路發達, 直接 link 別人寫的 : 什麼是指令集 )
第一種:
直接寫 .s 檔. 透過 compiler (gcc as ) 編譯.
這個可以像 之前介紹 libos 的方式. 修改 makefile 讓他編譯 .s
不過一般 user 可能比較難拿其他Arduino 板子來做. 侷限性比較大..
可能下回再詳細介紹
第二種:
arduino 和 ARM mbed 一樣, 都可以用 GCC 來當 compiler.
所以自然地, 我們可以寫 GCC inline assembly 來做.
這篇針對這個來介紹
網路上 GCC inline assembly 寫法說明也很多人寫.
英文版 :
http://www.ethernut.de/en/documents/arm-inline-asm.html
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s3
中文版 :
個人覺得這篇還算清楚
http://r40eubuntu.blogspot.tw/2009/02/arm-gcc-inline-assembler.html
為什麼要用組合語言, 其實關於這策略, 有些人會覺得全部用 C / C++ 寫就好了,
而且現在的最佳化做得很好, 也不一定要用組合語言.
不過在開發效能上, assembly 有時候的確是比用 C 來寫快速,
尤其是當 CPU 有這個指令的時候.
譬如做 byteswap
( byteswap 通常用在 endian 的轉換, endian 說明可以參考 wiki )
一般寫法可能是 C 的 macro 寫法, 做相對應的 shift / and operation
/* Swap bytes in 32 bit value. */ #define __bswap_constant_32(x) \ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #define __bswap_32(x) __bswap_constant_32 (x)
或 static inline function 寫法
static inline uint32_t __builtin_bswap32(uint32_t x) { return ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff); }
但 ARM 有針對這開發指令 : REV我們可以這麼寫 一個 bswap1 functionstatic inline int bswap1(int x) { asm volatile ( "rev %0, %1" : "=r" (x) : "r" (x) ); return x; }說明 :基本格式 : asm(code : output operand list : input operand list : clobber list);
%0 : 代表存取 輸出部分 (output operand)
%1 : 代表存取 輸入部分 (input operand)
此項沒有 clobber list
output operand "=r" (x)
= : write only , 一般 output 都會加
r : general register
x : C function 的變數. 用括號括起來
同樣的, 我們可以設計一個 RBIT. (整個 bit 反置)大家可以想想如果沒有 RBIT 指令, 要做 bit 反轉, 用 C 寫要做多少動作..這也是硬體指令集的優點.更多體現在 FPU (浮點運算 ) / DSP / 繪圖 (e.g. NEON) 等指令集, 來做這些一般更複雜的運算. 當然這些通常會做在 toolchain library, 一般使用者只要呼叫使用正確的 library (e.g. ARM newlib) /intrinsic functions 即可.如這份文件所說 :完整 Arduino 程式:----int thisByte; static inline int bswap1(int x) { asm volatile ( "rev %0, %1" : "=r" (x) : "r" (x) ); return x; } static inline int bit_reverse1(int x) { asm volatile ( "rbit %0, %1" : "=r" (x) : "r" (x) ); return x; } void setup() { //Initialize serial and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } thisByte = 0x11223344; Serial.print("Original data : 0x"); Serial.println (thisByte, HEX); thisByte = bswap1(thisByte); Serial.print("REV : 0x"); Serial.println (thisByte, HEX); thisByte = bit_reverse1(thisByte); Serial.print("RBIT : 0x"); Serial.println (thisByte, HEX); } void loop() { } ---- 執行結果: 一開始值是 : 0x11223344 做 byte swap (endian convert) 變為 0x44332211 用 0x44332211 整個做 bit 反轉 , 變為 0x8844CC22 ( 0x44332211 = 0b 0100 0100 0011 0011 0010 0010 0001 0001 ) ( 0x8844CC22 = 0b 1000 1000 0100 0100 1100 1100 0010 0010 )
留言
張貼留言