• 沒有找到結果。

指引指令 (提供組譯器)

N/A
N/A
Protected

Academic year: 2022

Share " 指引指令 (提供組譯器)"

Copied!
38
0
0

加載中.... (立即查看全文)

全文

(1)

NDS32 程式設計指南

(2)

綱要

 工具鏈

 NDS32 組合語言語法

 指引指令 (提供組譯器)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變(volatile)的關鍵字

(3)

綱要

 工具鏈

 NDS32 組合語言語法

 指引指令 (提供組譯器)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(4)

工具鏈

 環境變數 $PATH

 新增nds32-elf-as 和其他 GNU 工具鏈執行檔的路徑至環境變數

$PATH 變數值

• PATH=/home/users/yourdir/bin:$PATH

 c/c++ 編譯器

 nds32-elf-gcc

 組譯器

 nds32-elf-as

 連結器

 nds32-elf-ld

(5)

編譯器選項

 用法: nds32-elf-gcc [選項] 檔名...

 選項:

 -Wa,<選項> :傳送以逗號分隔的<選項>給組譯器

 -Wp,<選項> :傳送以逗號分隔的<選項>給前置處理器

 -Wl,<選項> :傳送以逗號分隔的<選項>給連結器

 -Xassembler <arg> :傳送參數 <arg>給組譯器

 -Xpreprocessor <arg>:傳送參數 <arg>給前置處理器

 -Xlinker <arg>:傳送參數 <arg>給連結器

 -E 只作前置處理; 不會編譯、組譯或連結

 -S 只用編譯; 不會組譯或連結

 -c 編譯和組譯,但是不會連結

 -o <檔案名稱> 指定輸出檔案名稱>

 -B <目錄> 加入 <目錄> 讓編譯器搜尋路徑

(6)

編譯器選項

 選項:

 -x <language> 指定輸入文件使用的程式語言,可用的語言為:C、

C++、Assembler,若無指定語言則恢復預設操作,以檔案副檔名 為語言的判定基準。

 -mno-16bit 不產生16位元的指令

 -m16bit 產生16位元的指令

 -mel 使用 little-endian 位元組順序

 -meb 使用 big-endian 位元組順序

 -mmw-count= 4~8,指定編譯多重載入/儲存指令時最大移動的 字組個數。預設為4。

 -mcache-line-size= 指定快取大小為 2 的次方個位元組。數值範 圍從 2 到 9。 預設是 2^4 (16) 位元組。

(7)

編譯器選項

 選項:

 -mcpu= 指定由哪一顆CPU產生程式碼: n1213-43u1h, n12, n10。

預設為 n12。

 -mlib= 指定連接 C 語言的哪一個程式庫: glibc 或 newlib。預設為 glibc。

 -g 在當前的操作系統格式產生除錯資訊(stabs、 COFF、XCOFF、

或 DWARF 2)。

 -EL 或 -little 產生 little endian 資料

 -EB 或 –big 產生 big endian 資料

 -O 或 -On 指定優化程度,其中 n=1-6。

 -Os 機器碼空間優化。

 -cpu 或 -mcpu=<cpuname> 指定CPU。

 -mno-16bit 不產生16位元指令

 -mfpu 支援浮點運算處理指令

 -mno-fpu 不支援浮點運算處理指令

(8)

組譯器選項

 nds32-elf-as [選項...] [組譯檔案...]

 選項:

 -D 產生組譯除錯訊息

 -g --gen-debug 生成除錯訊息

 -W --no-warn 不產生警告訊息(warnings)

• --warn

警告訊息

(warnings)

 -EL 或 -little 產生 little endian 資料

 -EB 或 -big 產生 big endian 資料

 -x assembler-with-cpp

• 指定原始檔語言: C、C++、Objective-C、或 assembly。

 -O or -On 指定優化程度,其中 n=1-6。

 -Os 作空間優化。

 -cpu or -mcpu=<cpuname>指定CPU

 -mno-16bit 不產生 16 位元指令

 -mfpu支援浮點運算處理指令

 -mno-fpu不支援浮點運算處理指令

(9)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (提供組譯器)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(10)

NDS32組合語言語法

 ‘#’和 ‘!’皆為註解符號, 但‘#’ 須在每列的第1行, ‘!’ 在任何地方 (除了括號內)皆可,後面的文字到行尾皆為註解。

 支援一行多個指令,但不建議使用,且每兩個指令間應該用 “;” 分開。

 一個整數可以指定為十進制、八進制(數值前需用 0 開頭)、十六進制 (數值前需用 0x 開頭)和二進制(數值前需用 0b 開頭)。例如:128、

#128、0200、#0200、0x80、#0x80、0b10000000、和

#0b10000000 都是相同。可選擇數值前是否加上 ‘#’ 符號。

 一個浮點數使用 ’e’ 和 ‘E’ 指定指數的部分,‘f’ 和 ‘F’ 為單精準 浮點數,以及 ‘d’ 和 ‘D’ 為倍精度浮點數。例如, 0f12.345 或 0d1.2345e12。

 組合語言指令是與大小寫無關,除非是使用者所定義的標籤。 例如:

“jral F1” 與 “jral f1” 這兩者是不相同的,但 “JRAL F1” 和第一個 指令是相同的。

(11)

暫存器 暫存器 暫存器 暫存器

 通用暫存器 通用暫存器 通用暫存器 通用暫存器 (GPR)

 所有 $r0-$r31 都用5個位元定址。

 4個位元定址的是 $h0-$h15,這些對應到 $r0-$r11 和 $r16-

$r19 。

 3個位元定址的是 $o0-$o7,對應到 $r0-$r7 。

 $ta是組譯器預留的暫存器

 由假指令轉譯時經常使用到$ta

 隱含指令暫存器 隱含指令暫存器 隱含指令暫存器 隱含指令暫存器

 暫存器 $r5: BEQS38 和 BNES38會將$r5當成運算元

 暫存器 $ta ($r15) : SLTI45、SLTSI45、SLT45、SLTS45、

BEQZS8 和 BNEZS8等會將$r15當成運算元

 暫存器 $fp ($r28): LWI37 和 SWI37會將$r28當成運算元

 當前系統預留的暫存器 當前系統預留的暫存器 當前系統預留的暫存器 當前系統預留的暫存器 $p0 和 和 和 和 $p1

(12)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (提供組譯器使用)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(13)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (提供組譯器)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(14)

指引指令 (組譯器指令)

 GNU預設支援指引指令的部份 預設支援指引指令的部份 預設支援指引指令的部份 預設支援指引指令的部份

 .data subsec 資料節區。

 .text subsec 程式碼節區。

 .bss subsec 未初始化資料節區。

 .section 使用者自行定義的部份。

 Andes支援指引指令的部份 支援指引指令的部份 支援指引指令的部份 支援指引指令的部份

 .sdata_d 倍字組大小 (8-byte) 的小型資料節區。

 .sdata_w 字組大小 (4-byte) 的小型資料節區。

 .sdata_h 半字組大小 (2-byte) 的小型資料節區。

 .sdata_b 位元組大小的小型資料節區。

 .sbss_d未初始化雙倍字組大小 (8-byte) 的小型資料節區。

 .sbss_w未初始化字組大小 (4-byte) 的小型資料節區。

 .sbss_h未初始化半字組大小 (2-byte) 的小型資料節區。

 .sbss_b未初始化位元組大小的小型資料節區。

(15)

指引指令 (組譯器指令)

 GNU 預設 預設 預設 預設 指引指令(符合 ELF)

 . align 種類、填滿、最大對齊種類

 .ascii 宣告“…” 字串常數

 .asciz宣告“…” 字串常數(以0作為結尾)

 .byte宣告位元資料

 .2byte宣告2位元組資料。 (非強制對齊)

 .4byte宣告4位元組資料。 (非強制對齊)

 .8byte宣告8位元組資料。 (非強制對齊)

 .double宣告倍精準精浮點常數。

 .equ symbol,expr 定義 符號 = expr運算式。

 .equiv symbol,expr 和 .equ 語法一樣,除非重複一個錯誤。

 .global symbol 定義整體符號常數。

 .globl symbol 和 .global 語法一樣。

(16)

指引指令 (組譯器指令)

 GNU 預設 預設 預設 預設 指引指令(符合 ELF)

 .if expr 判斷式成立則組譯。

 .else 有條件的組譯。

 .elseif 有條件的組譯。

 .endif 有條件組譯結束。

 .equ symbol,expr 定義 expr 數值。

 .equiv symbol,expr 和 .equ 語法一樣,除非重複一個錯誤。

 .def symbol 定義符號。

 .endef結束符號定義

 .ifdef symbol有條件的組譯

 .ifndef symbol 有條件的組譯。

 .end 程式結束

(17)

指引指令 (組譯器指令)

 GNU 預設 預設 預設指引指令支援 預設 支援 支援 支援 ELF

 .macro macname [macargs ...] 定義呼叫巨集呼叫的名稱。

 .endm 結束巨集定義的標誌。

 .exitm 提前離開當前的巨集定義。

 資料類型宣告的 資料類型宣告的 資料類型宣告的 資料類型宣告的指引指令

 .half 強制2位元組對齊。

 .int, .float, .long, .single, and .word: 強制2位元對齊。

 .double and .dword: 強制8位元對齊

 .qword: 強制16位元對齊

 如不想強制對齊,則使用以下方式

• .dc.h 或 .2byte for .half and .hword.

• .dc、.dc.l 和 .dc.w 或 .4byte for .int, .long, and .word.

• .dc.s 或 .4byte for .float and .single.

• .dc.d 或 .8byte for .double.

• .dc.x 或 extended (12-byte) 浮點數。

(18)

指引指令 (組譯器指令)

 空間類型宣告的 空間類型宣告的 空間類型宣告的 空間類型宣告的指引指令

 .dcb、.dcb.d、.dcb.h、dcb.l、dcb.s、dcb.w 和 .dcb.x。

 .ds、 .ds.d、.ds.h、.ds.l、ds.s 和 .ds.w。

 .space.

 .skip.

 .zero.

 .fill – 將指定填充的值放入填充資料區域。

(19)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (組譯器指令)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(20)

假指令

 載入32位元的數值/位址

 li rt5,imm_32 載入imm_32整數值到暫存器 rt5。

• sethi rt5,hi20(imm_32) 然後 ori rt5,reg,lo12(imm_32)

 la rt5,var 載入變數var的32位元位址到暫存器 rt5。

• sethi rt5,hi20(var) 然後 ori reg,rt5,lo12(var)

 載入/儲存 變數

 l.{bhw} rt5,var 載入變數var的值到暫存器 rt5.

• sethi $ta,hi20(var) 然後 l{bhw}i rt5,[$ta+lo12(var)]

 l.{bh}s rt5,var 載入有號數變數var的值到暫存器 rt5.

• sethi $ta,hi20(var) 然後 l{bh}si rt5,[$ta+lo12(var)]

 l.{bhw}p rt5,var,inc 載入變數var的值到暫存器 rt5 後,把inc加到

$ta

• la $ta,var 然後 l{bhw}i.p rt5,[$ta],inc

 l.{bhw}pc rt5,inc 持續載入變數var的值到暫存器 rt5 後,把inc加到

$ta

• l{bhw}i.bi $rt5,[$ta], inc

(21)

假指令

 載入/儲存 變數

 s.{bhw}p rt5,var,inc 將暫存器 rt5 的值儲存到 var 後,把inc加 到 $ta。

• la $ta,var 然後 s{bhw}i.p rt5,[$ta],inc

 s.{bhw}pc rt5,inc 持續的將暫存器 rt5的值儲存到 var 後,把inc 加到 $ta。

• s{bhw}i.p rt5,[$ta],inc

 l.{bh}sp rt5,var,inc 載入變數var的值到暫存器 rt5 後,把inc加到

$ta。

• la $ta,var 然後 l{bh}si.p rt5,[$ta],inc

 l.{bh}spc rt5,inc 持續的載入變數var的值到暫存器 rt5後,把inc 加到 $ta。

• l{bh}si.p rt5,[$ta],inc.

 s.{bhw} rt5,var 將暫存器 rt5的值儲存到 var 。

• sethi $ta,hi20(var) and then s{bhw}i rt5,[$ta+lo12(var)]

(22)

假指令

 反相

 not rt5,ra5 也能寫成 nor rt5,ra5,ra5 (取1的補數)

 neg rt5,ra5 也能寫成 subri rt5,ra5,0(取2的補數)

 跳躍至 標籤位址

 br rb5 也能寫成 jr rb5

• 取決於如何組譯,可以組譯成 “jr5 rb5” 或 “jr rb5”.

 b label 跳躍到 label

• 取決於如何組譯,可以組譯成

“j8 label”、“j label” 或 “la

$ta,label; br $ta”.

 beq rt5,ra5,label 或 beqz rt5,label 相等或等於0則跳躍

 bne rt5,ra5,label 或 bnez rt5,label 不相等或不等於0則跳躍

 bge{s} rt5,ra5,label 或 bgez rt5,label 大於或等於則跳躍

 bgt{s} rt5,ra5,label 或 bgtz rt5,label 大於則跳躍

 blt{s} rt5,ra5,label 或 bltz rt5,label 小於則跳躍

 ble{s} rt5,ra5,label 或 blez rt5,label 小於或等於則跳躍

(23)

假指令

 函數呼叫

 bral rb5 也能寫成 jral br5

• 取決於如何組譯,可以組譯成 “jral5 rb5” 或 “jral rb5”.

 bal fname 也能寫成 jal fname

• 取決於如何組譯,可以組譯成 “jal fname” 或 “la $ta,fname; bral

$ta”.

 call fname 和 call function fname

• 都是相同的 “jal fname”.

 bgezal rt5,fname 大於等於0則呼叫函式

 bltzal rt5,fname 小於0則呼叫函式

(24)

假指令

 搬移

 move rt5,ra5

• 16位元指令用法:等同 mov55 rt5,ra5

• 不使用16位元指令用法:等同 ori rt5,ra5,0

 move rt5,var 等同 l.w rt5,var

 move rt5,imm_32等同li rt5,imm_32

 推入/取出

 pushm ra5,rb5 將 ra5 ~ rb5的值 放入堆疊(SP)。

 push ra5 將 ra5 放入堆疊(SP)。(也可寫成 pushm ra5,ra5)

 push.d var 將雙字組大小的變數 var 放入堆疊。

 push.w var 將單字組大小的變數 var 放入堆疊。

 push.h var 將半字組大小的變數 var 放入堆疊。

(25)

假指令

 推入/取出

 push.b var 將位元組大小的變數 var 放入堆疊。

 pusha var 將變數 var的32位元記憶體址值放入堆疊。

 pushi imm_32 將32位元立即值放入堆疊。

 popm ra5,rb5 將堆疊頂端的數值放入 ra5 ~ rb5。

 pop rt5 將堆疊頂端的數值放入 rt5。(也可寫成 popm rt5,rt5)

 pop.d var,ra5 從堆疊頂端取出雙字組,第二個字組放入 ra5,第 二個字組放入ta

 pop.w var,ra5 從堆疊暫存器取出一個字組放入ra5。

 pop.h var,ra5 從堆疊暫存器取出半個字組放入ra5。 。

 pop.b var,ra5 從堆疊暫存器取出一個位元組放入ra5。 。

(26)

內建運算函數

 以下內建運算函數可以用在任何組合語言指令:

 hi20(var) 取出變數var記憶體位址的最高20個位元

 lo12(var) 取出變數var記憶體位址的最低12個位元

 sda(var) 取出變數var距離小型資料區15位元的位移量

(27)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (組譯器指令)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(28)

巨集

 假運算元:

 .macro: 開始定義巨集

 .endm: 結束定義巨集

 .exitm: 離開定義巨集

 通用暫存器 $r15 ($ta) 是組譯器預留給巨集擴展和其他 用途所使用的。

 所有假指令(pseudo-codes)皆是以巨集實現

 “li rt5,imm32”

.macro load_imm32 rt5,imm32

!Copyright c 2006-2007 Andes Technology Corporation 33 .if ((imm32 <= 0x7ffff) && (imm32 >= -0x80000))

movi rt5,imm32

.elseif (imm32 & 0x00000fff == 0x0) sethi rt5,hi20(imm32)

.else

sethi rt5,hi20(imm32) ori rt5,rt5,lo12(imm32)

.endif

.endm

(29)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (組譯器指令)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(30)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (組譯器指令)

 假指令 (機械碼)

 巨集

 行內組合語言

(31)

行內組合語言

 可以減少因呼叫函數產生的多餘的程式碼

 有助於系統程式的編寫

 中斷處理程式

 存取系統暫存器

 程式碼優化

 基本的行內組合語言

 asm (“statements”); 或 __asm__ ("statements");

 asm (“statement1

\n\t”

“statement2\n\t”

“statement3”);

asm( “jal 4 \n\t”

“move $r6, $lp\n\t\”

“jr $r6”

) ;

(32)

行內組合語言

 擴充的行內組合語言

 asm ( assembler template

: output operands /* optional */

: input operands /* optional */

: list of clobbered registers /* optional */

);

int num1=10, num2=20, sum;

asm (

"add %0, %1, %2"

:"=r"(sum)

:"r" (num1), "r" (num2) );

int num1=10, num2=20, sum;

asm (

"add %[summary], %[intg1], %[intg2]"

:[summary]"=r"(sum)

:[intg1] "r" (num1), [intg2]"r" (num2)

);

(33)

行內組合語言

規範 規範 規範

規範 用法用法用法用法

l $d0.lo 或 $d1.lo

h $d0.hi 或 $d1.hi

x $d0 或 $d1

A $d0.lo

B $d0.hi

C $d1.lo

D $d1.hi

r 通用暫存器

Modifier

意義

= 只能寫入的動作,通常用於所有輸出的動作

+ 讀寫動作,必須被列為輸出的動作

& 一個暫存器,只能用於輸出作用

(34)

概要

 工具鏈

 NDS32 組合語言語法

 指引指令 (組譯器指令)

 假指令 (機械碼)

 巨集

 行內組合語言

 C 和 易變的關鍵字

(35)

易變的關鍵字

 如果變數宣告時加上volatile 關鍵字時,等同告訴編譯器 這是一個可能會在任何時間改變數值的變數 (即使編譯器 從程式碼中找不到任何這變數的程式碼 )。

 三種類型的變數可能會隨時更動:

 1. 記憶體映射的周邊暫存器

 2. 會受中斷服務程式修改的全域變數

 3. 在多執行緒應用程式中多個執行續存取的全域變數

 上述類型的變數應該被相同的宣告為 “volatile”。

(36)

變數宣告沒有 volatile 關鍵字

#define inw(reg) (*((unsigned int *) (reg)))

#define outw(reg, data) ((*((unsigned int *)(reg)))=(unsigned int)(data)) /* GPIO controller */

#define GPIO_BASE 0x98100000 /* GPIO base address */

#define GPIO_DIN_OFFSET 0x4

int main(void) {

int j;

while (inw(GPIO_BASE + GPIO_DIN_OFFSET)==0) j=1;

return 1;

} 000082ac <main>:

82ac: 51 ff ff f8 addi $sp,$sp,#-8 82b0: 15 cf 80 01 swi $fp,[$sp+#4]

82b4: 83 9f mov55 $fp,$sp 82b6: 46 59 81 00 sethi $r5,#622848 82ba: 58 52 80 04 ori $r5,$r5,#0x4 82be: b4 a5 lwi450 $r5,[$r5]

82c0: 84 60 movi55 $r3,#0

82c2: db 02 bnes38 $r3,82c6 <main+0x1a>

82c4: c5 00 beqz38 $r5,82c4 <main+0x18>

82c6: 84 01 movi55 $r0,#1 82c8: 83 fc mov55 $sp,$fp 82ca: 05 ce 00 01 lwi $fp,[$fp+#4]

82ce: 51 ff 80 08 addi $sp,$sp,#8 82d2: dd 9e ret5 $lp

(37)

用 volatile 關鍵字宣告變數

#define inw(reg) (*((volatile unsigned int *) (reg)))

#define outw(reg, data) ((*((volatile unsigned int *)(reg)))=(unsigned int)(data)) /* GPIO controller */

#define GPIO_BASE 0x98100000 /* GPIO base address */

#define GPIO_DIN_OFFSET 0x4

int main(void) {

int j;

while (inw(GPIO_BASE + GPIO_DIN_OFFSET)==0) j=1;

return 1;

} 000082ac <main>:

82ac: 51 ff ff f8 addi $sp,$sp,#-8 82b0: 15 cf 80 01 swi $fp,[$sp+#4]

82b4: 83 9f mov55 $fp,$sp 82b6: 46 49 81 00 sethi $r4,#622848 82ba: 58 42 00 04 ori $r4,$r4,#0x4 82be: b4 a4 lwi450 $r5,[$r4]

82c0: c5 ff beqz38 $r5,82be <main+0x12>

82c2: 84 01 movi55 $r0,#1 82c4: 83 fc mov55 $sp,$fp 82c6: 05 ce 00 01 lwi $fp,[$fp+#4]

82ca: 51 ff 80 08 addi $sp,$sp,#8 82ce: dd 9e ret5 $lp

(38)

存取記憶體映射 I/O

 宣告和存取

 #define GPIOBASE_PTR (volatile unsigned char *) 0x98700000

• *(GPIOBASE_PTR) = 0x55

• GPIOBASE_PTR 被宣告為指標變數,指向記憶位址 0x98700000

 #define GPIOBASE (* (volatile unsigned char *) 0x98700000)

• GPIOBASE = 0x55

• GPIOBASE 被宣告為普通無正負號的字元變數,儲存在記憶體位址

0x98700000

參考文獻

相關文件

Nature of outing 活動性質 Date 日期 Time 時間. From

戶外考察活動 是歷史 科教師於課堂教學 以 外評估學生的常見方法。教師 在外 出之前應為學 生提供 明確的學習目標和 評 估準則。教師可以從以

[r]

個人資料」、「職業退休豁免計劃指《職業退休計劃條例》所指的職業退休計

之意,此指依照命令動作的意義。所謂伺服 系統,就是依照指示命令動作所構成的控制

(A)SQL 指令是關聯式資料庫的基本規格(B)只有 SQLServer 2000 支援 SQL 指令(C)SQL 指令 複雜難寫,適合程式進階者使用(D)是由 Oracle

研習影響工業區位的各種因素是地理科的一個重要課題。本主題旨在以鋼

災害發生,由指揮官發布救災指示於各分組之負責人,再由負責人指派分組