第三章 ARM的介紹
ARM(Advanced RISC Machines Limited) 用於低電力與低成本的embedded system Mobile phone Communication modem Engine management system PDA
ARM7 Byte-addressable memory(可定址位元組的記憶體) 32 bits register and addressing Most instructions execute in a single cycle Every instruction can be conditionally executed Support both little-endian and big-endian (determined by control line of CPU) Word alignment (multiple of 4) Memory access(8/32 bits) can only via Load, Store, which is main feature of RISC All ALU operations are register-register (No register-memory) 16 32-bit registers R0~R15,where R0~R12 are GPR and R13 is the stack pointer, R14 is link register(return address when call sub) R15 is the program counter CPSR-Current program Status Register (status register-N,Z,C,V,NMI,Processor mode)
ARM instruction format
表 3.1 ARM 的索引定址模式 名稱 組譯程式語法 定址函數 包含立即偏移量: 前置索引 [Rn,#offset] EA = [Rn] + offset 包含寫回的前置索引 [Rn,#offset]! EA = [Rn] + offset; Rn ← [Rn] + offset 後置索引 [Rn],#offset EA = [Rn]; 在 Rm 中包含偏移量大小: [Rn,±Rm,shift] EA = [Rn]±[Rm]移位 [Rn,±Rm,shift]! EA = [Rn]±[Rm]移位; Rn ← [Rn]±[Rm]移位 [Rn],±Rm,shift 相對(包含立即偏移量的前置索引) Location EA = Location = [PC] + offset EA = 有效位址 offset = 位於指令中的有號數 shift = 有向整數,其中左移的方向為 LSL,或是右移的方向為 LSR,整數 為用來指定移位量的 5 位元無號數 ±Rm = 位於暫存器 Rm 中,可以被加入基底暫存器 Rn ,或是減去 Rn 的偏移量大小
ARM 定址模式 前置與後置索引的定址方式是依[ ]的使用方式加以區別 若只有基底暫存器(Rn)被[ ]括起來,則叫後置索引定址,記憶方式因為offset在’]’之後 若基底暫存器(Rn)與offset被[ ]括起來,則叫前置索引定址,記憶方式因為offset在’]’之前 前置索引模式(Pre-indexed mode):EA=base register Rn的內容+offset LDR Rd,[Rn,#offset] ; Rd [[Rn] + offset] (cf.索引定址p2-29) LDR Rd,[Rn,Rm] ;Rd [[Rn] + [Rm]],(cf.索引基底)Rn,Rm的內容表示Address,裡面的[]是ARM assembly的語法,外面的 []是定址的語法 包含寫回的前置索引模式(Pre-indexed mode/writeback): EA=base register Rn的內容+offset,且Rn EA類似自動定址 LDR R0,[R1-R2]! ; R0 [[R1]-[R2]], R1 [R1]-[R2] STR R0,[R5,#-4]! ; [[R5] -4] R0, R5 [R5] – 4(見p3-11圖3.4(b)) LDR R0,[R1.-R2,LSL #4]! ; R0 [[R1] -16 * [R2]], R1 [R1]-16*[R2] STR R3,[R5,R6] ; [[R5]+[R6]] R3 後置索引模式(Post-indexed mode):EA= base register Rn的內容(cf.間接定址),且Rn EA+offset(自動定址) 注意:只要EA一產生就表示CPU接著會到此位址拿資料 LDR R3,[R2],#4 ; R3 [[R2]], R2 [R2] + 4 (見p3-20) LDR R1,[R2],R10,LSL#2 ; R1 [[R2]], R2 [R2]+[R10] * 4 相對定址 LDR R1, ITEM ; EA=ITEM的位址=[PC]+offset,where PC為加8後的值,所以offset = ITEM – 8 注意ARM沒有絕對(直接)定址,所以不要將LDR R1, ITEM 解讀為絕對(直接)定址
ARM 定址模式(cont’d) 圖 3.3 ARM 的記憶體定址模式範例 (a) 相對定址模式 (b) 前置索引定址模式 字組 (4個位元組) 記憶體位址 Item為Location 1000 LDR R1, ITEM 1004 - For pipeline 1008 - 更新的 [PC] = 1008 * * * * 52 =偏移量 * * ITEM = 1060 運算元 (a) 相對定址模式 STR R3, [R5, R6] 1000 R5 * 基底暫存器 * * 200 R6 1000 偏移暫存器 * * * * 200 =偏移量 * * 1200 運算元 (b) 前置索引定址模式 圖 3.3 ARM 的記憶體定址模式範例
圖 3.4 涉及寫回的 ARM 記憶體定址模式 (a) 包含寫回的後置索引定址 (b) 包含寫回的前置索引定址 記憶體位址 字組 (4個位元組) 1000 6 1000 R2 * 基底暫存器 100 = 25 x 4 * * 25 R10 1100 -17 偏移暫存器 * * 100 = 25 x 4 * Load 指令: 1200 321 LDR R1,[R2],R10,LSL #2 (a) 包含寫回的後置索引定址 2012 R5 堆疊指標 2008 27 27 R0 2012 - Push 指令: 執行過 Push 指令之後 [[R5]-4] R0 R5 [R5]-4 STR R0,[R5,#-4]! (b) 包含寫回的前置索引定址 圖 3.4 涉及寫回的 ARM 記憶體定址模式
Format (a) examples OP{Cond}{S} Rd,Rn,Operand2 ADD R0,R1,R2 Only operand2 can be shifted ADD R0,R1,R2 無條件執行 R0 [R1]+[R2] ADDEQ R0,R1,R2 有條件執行 當Flag Z=1時 R0 [R1]+[R2] ADDEQS R0,R1,R2 同上,但會影響Flag (設定CPSR中的Flag) Why predicated instruction? To eliminate conditional branch in small if-then-elseeasy to write compact code for embedded system If(a==b) { a++; } else { a--; } CMP R1,R2 /*assume a in R1, b in R2*/ ADDEQ R1,#1 /*add 1 when equal*/ SUBNE R1,#1 /*sub 1 when not equal*/ CMP R1,R2 /*assume a in R1, b in R2*/ BNE Next ADD R1,#1 /*add 1 when equal*/ Next SUB R1,#1 /*sub 1 when not equal*/
Format (a) examples(cont) ADD R0,R1,#17 R0 [R1]+17 ADD R0,R1,R2,LSL #4 R0 R1 + R2 * 16 ADD R0,R1,R2, LSR R3 R0 R1 + R2 / 2[R3]
Format (b) examples MUL R1,R2,R3 MLAEQS R1,R2,R3,R4 R1:=R2*R3 MUL{cond}{S} Rd,Rm,Rs MLA{cond}{S} Rd,Rm,Rs,Rn {cond} two-character condition mnemonic. Condition code summary on page B-4. {S} set condition codes if S present Rd, Rm, Rs and Rn are expressions evaluating to a register number other than R15. MUL R1,R2,R3 R1:=R2*R3 MLAEQS R1,R2,R3,R4 Conditionally R1:=R2*R3+R4,setting condition codes.
Format (c) examples <LDR|STR>{cond}{B}{T} Rd,<Address> {B} if B is present then byte transfer, otherwise word transfer {T} if T is present the W bit will be set in a post-indexed instruction, forcing non-privileged mode for the transfer cycle. T is not allowed when a pre-indexed addressing mode is specified or implied. LDR Rd,[Rn,#offset] Rd [[Rn]+offset] LDR R0,[R13,#4] (見p3-27) R0 [[R13]+4] LDR Rd,[Rn,Rm] Rd [[Rn]+[Rm]] LDR R1,[R2,R3] R1 [[R2]+[R3]] LDR R3,[R2],#4 R3 [[R2]], R2 [R2] + 4 STR R0,[R13,#-4]! R0 [[R13] – 4], R13 [R13] - 4
Format (d) examples <LDM|STM>{cond}<FD|ED|FA|EA|IA|IB|DA|DB> Rn{!},<Rlist>{^} where:{cond} two character condition mnemonic. Rn is an expression evaluating to a valid register number <Rlist> is a list of registers and register ranges enclosed in {} (e.g. {R0,R2-R7,R10}). {!} if present requests write-back (W=1), otherwise W=0 {^} if present set S bit to load the CPSR along with the PC, or force transfer of user bank when in privileged mode pre-increment load LDMED post-increment load LDMFD pre-decrement load LDMEA post-decrement load LDMFA pre-increment store STMFA post-increment store STMEA pre-decrement store STMFD post-decrement store STMED STMFD R13!,{R3,R14} (見p3-26) FD表堆疊朝低位址成長 R13 [R13]-4, [R13] R14, R13 [R13]-4, [R13] R3 Store direction from Right to Left LDMFD R13!,{R3,R15} (見p3-26) FD表堆疊朝低位址成長 R3 [R13], R13 R13+4, R15 [R13], R13 R13+4 Restore direction from Left to Right
Format (e) examples Items in {} are optional. Items in <> must be present. B{L}{cond} <expression> {L} is used to request the Branch with Link form of the instruction. If absent, R14 will not be affected by the instruction. {cond} is a two-character mnemonic, If absent then AL(ALways) will be used. {Cond} 見 pB-4 表B.1 <expression> is the destination. The assembler calculates the offset. BL LISTADD (見p3-26) BGT LOOP (見p3-26)
圖 3.11 把圖 3.7 的程式改寫成 ARM 副常式的程式;參數透過堆疊來傳遞 (假定堆疊頂端位於以下第一層) 注意ARM沒有直接定址,所以在此是相對定址 呼叫程式 LDR R0,POINTER 把 NUM1 推入堆疊 R13R13 – 4 [R13] R0 STR R0,[R13,# – 4]! LDR R0,N 把 n 推入堆疊 – STR R0,[R13,# 4]! 注意ARM沒有直接定址,所以在此是相對定址 BL LIST ADD R14指向下一個指令 LDR R0,[R13,#4] 把總和移入記憶體位置 SUM 此時R13指向n, Get NUM1 STR R0,SUM ADD R13,R13,#8 從堆疊上移除參數 . . . R13 [R13]-4, [R13] R14; R13 [R13]-4, [R13] R3; R13 [R13]-4, [R13] R2; R13 [R13]-4, [R13] R1; R13 [R13]-4, [R13] R0 副常式 LIST ADD STMFD R13!, { R0 – R3,R14 } 儲存暫存器 LDR R1,[R13,#20] 從堆疊上載入參數 LDR R2,[R13,#24] MO V R0,#0 Get n LOOP LDR R3,[R2],#4 ADD R0,R0,R3 Get NUM1 SUBS R1,R1,#1 Get NUM1(注意事後置索引定),R3[[R2]],R2[R2]+4 BGT LOOP 存入NUM1 STR R0,[R13,#24] 把總和放上堆疊 LDMFD R13!, { R0 – R3,R15 } 回復暫存器並且回傳 (a) 呼叫程式與副常式 第三層 [R0] [R1] [R2] [R3] 回傳位址 2nd STR R0,[R13,#-4] 第二層 n 1st STR R0,[R13,#-4] NUM1 Old TOS 第一層 (b) 不同時期的堆疊頂端 圖 3.11 把圖 3.7 的程式改寫成 ARM 副常式的程式;參數透過堆疊來傳遞
圖 3.12 ARM 組合語言的巢狀副常式 記憶體位址 指令 註解 呼叫程式 – – 指回舊的TOS 第一個副常式 – param1 2000 LDR R10,P ARAM2 把參數放上堆疊 – 2004 STR R10,[SP, # 4]! 2008 LDR R10,PARAM1 2020存入R14(LR) 不會自動push RET ADDR – 2012 STR R10,[SP, # 4]! 2016 BL SUB1 2020 LDR R10,[SP] 儲存 SUB1 的結果 此時SP指向param1 2024 STR R10,RESUL T 2028 ADD SP, SP, #8 從堆疊上移除參數 2032 下一個指令 指回舊的TOS . . . Push LR Push FP Push R3 Push R2 Push R1 Push R0 此時SP指在R0 第一個副常式 – 2100 SUB1 STMFD SP!, { R0 R3,FP, LR } 儲存暫存器 2104 ADD FP, SP ,#16 載入窗格指標 2108 LDR R0,[FP, #8] 載入參數 2112 LDR R1,[FP, #12] param1 設定called fun的FP此時FP指向[FP] from Main(見下圖) . . . param2 LDR R2,P ARAM3 把結果放上堆疊 – STR R2,[SP, # 4]! 相當於Push param3 LR(R14) 2164 2160 BL SUB2 2164 LDR R2,[SP],#4 取出 SUB2 的結果並且放 入 R2 . R2[[SP]];SP[SP]+4 . . 此時SP指向param3 ,注意在此是後置索引定址 STR R3,[FP, #8] 把結果放上堆疊 存入param1 – LDMFD SP!, { R0 R3,FP, PC } 回復暫存器並且回傳 第二個副常式 此時SP指向[R0]from SUB1 3000 SUB2 STMFD SP!, { R0,R1,FP, LR } 儲存暫存器 建立sub2的FP ADD FP, SP, #8 載入窗格指標 LDR R0,[FP, #8] 載入參數 Param 3 . . . 存入param3 STR R1,[FP, #8] 把結果放上堆疊 LDMFD SP!, { R0,R1,FP, PC } 回復暫存器並且回傳 Pop R0 Pop R1 Pop FP Pop PC 圖 3.12 ARM 組合語言的巢狀副常式
圖 3.13 圖 3.12 的 ARM 堆疊窗格 低記憶體位址 高記憶體位址 [R0] from SUB1 [R1] from SUB1 第二個副常式 的堆疊窗格 FP [FP] from SUB1 2164 param3 [R0] from Main [R1] from Main [R2] from Main [R3] from Main 第一個副常式 的堆疊窗格 FP [FP] from Main 2020 SUB1中STMFD param1 param2 舊的 TOS 高記憶體位址 圖 3.13 圖 3.12 的 ARM 堆疊窗格
圖 3.15 ARM 版本的位元組排序程式 (a) 排序的 C 語言程式 (b) ARM 程式的實作 for (j = n – 1; j > 0; j = j – 1) { for ( k = – j 1; k > = 0; k = k – 1 ) { if (LIST[ k ] > LIST[ j ] ) { TEMP = LIST[ k ]; LIST[ k ] = LIST[ j ]; LIST[ j ] = TEMP; } } } (a) 排序的 C 語言程式 ADR R4,LIST 載入串列指標暫存器 R4, 把外部迴圈的基底暫存器 R2 初始化為 LIST + n LDR R10,N ADD R2,R4,R10 ADD R5,R4,#1 把 LIST + 1 載入 R5 OUTER LDRB R0,[R2,# – 1]! 把 LIST(j) 載入 R0 MO V R3,R2 把內部迴圈的基底暫存器 R3 初始化為 LIST + n – 1 – INNER LDRB R1,[R3,# 1]! 把 LIST(k) 載入 R1 CMP R1,R0 比較 LIST(j) 跟 LIST(k) STR GTB R1,[R2] 若LIST(k)>LIST(j)則交換 LIST(k)與LIST(j),並且把 (新的)LIST(j) 移入 R0 STR GTB R0,[R3] MO V GT R0,R1 CMP R3,R4 若 k > 0 則重複內部迴圈 BNE INNER CMP R2,R5 若 j > 1 則重複外部迴圈 BNE OUTER (b) ARM 程式的實作 圖 3.15 ARM 版本的位元組排序程式
Jump to IA-32 Pentium page 3-67 Skip to slide 26
圖 3.18 68000 的暫存器結構 長字組 字組 資料暫存器 位址暫存器 堆疊指標 程式計數器 使用者堆疊指標 系統管理者堆疊指標 位元組 31 16 15 8 7 D0 D1 D2 D3 資料暫存器 D4 D5 D6 D7 A0 A1 A2 A3 位址暫存器 A4 A5 A6 使用者堆疊指標 A7 堆疊指標 系統管理者堆疊指標 PC 程式計數器 15 13 10 8 4 SR 狀態暫存器 T-追蹤模式選單 C - 進位 S-系統管理者模式選擇 V - 溢位 I-中斷遮罩 Z - 零 N - 負 X - 擴充 圖 3.18 68000 的暫存器結構
圖 3.21 68000 指令 ADD # 9,D3 (a) ADD 指令的 OP 碼程式 (b) OP 碼字組的編碼 (c) 執行的結果 15 12 11 9 8 7 6 5 1 1 1 dst src 大小 OP 碼 (a) ADD 指令的 OP 碼程式 二進位 1 1 1 1 1 1 1 1 1 1 十六進位 D 6 7 C (b) OP 碼字組的編碼 i D67C OP 碼字組 i + 2 9 立即運算元 i + 4 D3 25 D3 34 PC i PC i + 4 提取指令之前 執行指令之後 (c) 執行的結果 圖 3.21 68000 指令 ADD # 9,D3
圖 3.22 C ← [A] + [B] 的 68000 常式 執行完畢之後 , [202200] = 424 A = 201150 639 10 B = 201152 - 215 10 201200 OP 碼字組 201202 20 MOVE A,D0 201204 1150 201206 OP 碼字組 201208 20 ADD B,D0 20120A 1152 20120C OP 碼字組 20120E 20 MOVE D0,C 201210 2200 C = 202200 執行完畢之後 , [202200] = 424 10 圖 3.22 C ← [A] + [B] 的 68000 常式
(a) 呼叫程式與副常式 (b) 不同時期的堆疊頂端 圖 3.29 把圖 3.26 的程式改寫成 ARM 副常式的程式;參數透過堆疊來傳遞 (假定堆疊頂端位於以下第一層) 呼叫程式 MO VE.L #NUM1, – (A7) 把參數推上堆疊 MO VE.L N, – (A7) BSR LIST ADD MO VE.L 4(A7),SUM 儲存結果 ADDI.L #8,A7 回復堆疊頂端 . . . 副常式 – – LIST ADD MO VEM.L D0 D1/A2, (A7) 儲存暫存器 D0、D1、A2 MO VE.L 16(A7),D1 把計數器初始化為 n SUBQ.L #1,D1 使用 DBRA 調整計數 MO VEA.L 20(A7),A2 讓指標指向串列 CLR.L D0 把總和初始化為 0 LOOP ADD.W (A2)+,D0 加入串列的項目 DBRA D1,LOOP MO VE.L D0,20(A7) 把總和放上堆疊 – MO VEM.L (A7)+,D0 D1/A2 回復暫存器 R TS (a) 呼叫程式與副常式 第三層 [D0] [D1] [A2] 第二層 回傳位址 n NUM1 第一層 (b) 不同時期的堆疊頂端 圖 3.29 把圖 3.26 的程式改寫成 ARM 副常式的程式;參數透過堆疊來傳遞
圖 3.30 68000 組合語言的巢狀副常式 記憶體位址 指令 註解 呼叫程式 第一個副常式 第二個副常式 儲存暫存器 . . . 2000 MO VE.L P ARAM2, – (A7) 把參數放上堆疊 2006 MO VE.L P ARAM1, – (A7) 2012 BSR SUB1 2014 MO VE.L (A7),RESUL T 儲存結果 2020 ADDI.L #8,A7 回復堆疊層級 2024 下一個指令 . . . 第一個副常式 2100 SUB1 LINK A6,#0 設定窗格指標 – – 2104 MO VEM.L D0 D2/A0, (A7) 儲存暫存器 MO VEA.L 8(A6),A0 載入參數 MO VE.L 12(A6),D0 . . . – MO VE.L P ARAM3, (A7) 把參數放上堆疊 2160 BSR SUB2 2164 MO VE.L (A7)+,D1 取出 SUB2 的結果並且放 入 D1 . . . MO VE.L D2,8(A6) 把結果放上堆疊 – MO VEM.L (A7)+,D0 D2/A0 回復暫存器 UNLK A6 回復窗格指標 R TS 回傳 第二個副常式 3000 SUB2 LINK A6,#0 設定窗格指標 MO VEM.L D0 – D1, – (A7) 儲存暫存器 MO VE.L 8(A6),D0 載入參數 . . . MO VE.L D1,8(A6) 把結果放上堆疊 MO VEM.L (A7)+,D0 – D1 回復暫存器 UNLK A6 回復窗格指標 R TS 回傳 圖 3.30 68000 組合語言的巢狀副常式
圖 3.31 圖 3.30 的 68000 堆疊窗格 [D0] from SUB1 [D1] from SUB1 A6 第二個副常式 的堆疊窗格 A6 [A6] from SUB1 2164 param3 [D0] from Main [D1] from Main [D2] from Main [A0] from Main 第一個副常式 的堆疊窗格 A6 [A6] from Main 2014 param1 param2 舊的 TOS 圖 3.31 圖 3.30 的 68000 堆疊窗格
圖 3.34 68000 的位元組排序程式 (a) 排序的 C 語言程式 (b) 68000 程式的實作 for (j = n 1; j > 0; j = j 1) { for ( k = j 1; k > = 0; k = k 1 ) { if (LIST[ k ] > LIST[ j ] ) { TEMP = LIST[ k ]; LIST[ k ] = LIST[ j ]; LIST[ j ] = TEMP; } } } (a) 排序的 C 語言程式 MO VEA.L #LIST,A1 指向串列開始的指標 MO VE N,D1 初始化位於 D1 的外部迴圈索引 j SUBQ #1,D1 OUTER MO VE D1,D2 初始化位於 D2 的內部迴圈索引 k SUBQ #1,D2 MO VE.B (A1,D1),D3 D3 存放目前的最大值 INNER CMP .B D3,(A1,D2) 若LIST(k)[D3] BLE NEXT MO VE.B (A1,D2),(A1,D1) 交換LIST(k)與LIST(j),並且把新 的最大值載入 D3 MO VE.B D3,(A1,D2) MO VE.B (A1,D1),D3 NEXT DBRA D2,INNER 遞減計數器 k 與 j,若是尚未完成 工作則跳回 SUBQ #1,D1 BGT OUTER (b) 68000 程式的實作 圖 3.34 68000 的位元組排序程式
IA-32 Pentium IA-32 : Intel Architecture 32 bits 80386 (1985)– 1st generation 80486 (1989) Pentium (1993) Pentium Pro (1995) Pentium II (1997) Pentium III (1999) Pentium IV (2000)
IA-32 Byte-addressable memory(可定址位元組的記憶體) 8/32 bits register and addressing little-endian byte alignment (不須對齊記憶體) 8 32-bit registers R0~R7, 8 64-bit floating point registers which can extend to 80 bits CS:code segment DS:data segment SS:stack segment ES:extra segment FS,GS:Data Segment Eflags Register(CF,ZF,SF,OF,IOPL,IF,TF) OPcode dst,src
IA-32定址模式 表 3.3 IA-32 的定址模式 名稱 組譯程式語法 定址函數 立即 Value 運算元 = Value 直接 Location EA = Location 暫存器 Reg EA = Reg, 也就是運算元 = [Reg] 暫存器間接 [Reg] EA = [Reg] 包含位移量的基底 [Reg + Disp] EA = [Reg] + Disp 包含位移量的索引 [Reg * S + Disp] EA = [Reg] × S + Disp 包含索引的基底 [Reg1 + Reg2 * S] EA = [Reg1] + [Reg2] × S 包含索引與位移量的索引 [Reg1 + Reg2 * S + Disp] EA = [Reg1] + [Reg2] × S + Disp Value = 8 位元或 32 位元的有號數 Location = 32 位元位址 Reg,Reg1,Reg2 = 通用暫存器 EAX、EBX、ECX、EDX、ESP、EBP、ESI、 EDI 之一,其中 ESP 無法被用於索引暫存器 Disp = 8 位元或 32 位元的有號數,其中在包含位移量的索引模式 中只能使用 32 位元。 S =縮放因子 1、2、4、或 8
立即定址模式 Mov EAX,25 EAX 25 (decimal) Mov EAX, 3FA00h EAX 3FA00 (Hex)
直接(絕對)定址模式 Mov EAX,LOCATION EAX (LOCATION) LOCATION表示記憶體位址,i.e. EA=LOCATION 如果LOCATION=1000,則表示1000~1003這四個記憶體的內容被COPY到EAX
立即定址vs直接定址 Number EQU 25 (組譯指引命令) Mov EAX, Number (立即定址) 但若Number本身已經是”位址標記”時,則不需要括號 Mov EAX,Number (直接定址) 假設LOCATION為”位址標記=1000”,則Mov EBX,OFFSET LOCATION (立即定址)把1000 copy 到 EBX,通常接下來的指令為 Mov EAX,[EBX] (暫存器定址,EA=EBX的內容) The OFFSET operator returns the offset of a memory location Mov EBX, offset LOCATION can be rewritten as LEA EBX, LOCATION Where LEA means Load Effective Address
包含位移的基底定址模式 Mov EAX,[EBP+60] ; 運算元位址(EA) = [EBP] + 60
包含索引與位移的基底定址模式 Mov EAX,[EBP+ESI*4+200]; EA= =[EBP] + [ESI] x 4+200
圖 3.37 IA-32 的暫存器結構 8個通用 暫存器 8個浮點數 暫存器 6個區段 暫存器 指令指標 31 R0 R1 R7 63 R0 R1 8個通用 暫存器 R7 63 FP0 FP1 8個浮點數 暫存器 FP7 16 程式區段 CS 堆疊區段 SS DS 6個區段 暫存器 ES 資料區段 FS GS 31 指令指標 31 13 12 11 9 8 7 6 狀態暫存器 輸入/輸出 特權等級 CF – 進位 ZF – 零 OF – 溢位 SF – 正負號 IF – 中斷啟用 TF – 陷阱 圖 3.37 IA-32 的暫存器結構
圖 3.38 IA-32 暫存器結構跟之前 Intel 處理器暫存器結構的相容性 通用命名方式 31 16 15 8 7 R0 EAX AH AL AX R1 ECX CH CL CX 資料暫存器 R2 EDX DH DL DX R3 EBX BH BL BX R4 ESP SP 指標暫存器 R5 EBP BP R6 ESI SI 索引暫存器 R7 EDI DI EIP IP 指令暫存器 EFLAGS FLAGS 狀態暫存器 圖 3.38 IA-32 暫存器結構跟之前 Intel 處理器暫存器結構的相容性 Figure 3.38. Compatibility of the IA-32 register structure
圖 3.39 IA-32 架構的定址模式範例 (a) 包含位移量的基底模式,表示為 [EBP + 60] 主記憶體 位址 雙字組 1000 基底暫存器 1000 * * * * 60 = 位移量 * * 1060 運算元 運算元位址(EA) = [EBP] + 60 (a) 包含位移量的基底模式,表示為 [EBP + 60] 1000 基底暫存器 1000 40 * * 索引暫存器 * * * * 200 = 位移量 1200 縮放因子 = 4 (雙字組) 4 位元組資料 項目的列表 * * * * 160 =[索引暫存器]x 4 * * 1360 運算元 * * * * * * * * * * * * 運算元位址(EA) =[EBP] + [ESI] x 4+200 (b) 包含索引與位移量的基底模式,表示為 [EBP + ESI*4 + 200] 圖 3.39 IA-32 架構的定址模式範例
IA-32指令與IA-32組合語言 Most instructions One or two operands For two operands, either two of them are registers or one of them is register. Two memory locations are not allowed 組合語言 見P3-87圖3.42
圖 3.40 用來累加數值的 IA-32 程式 (a) 直接方式 (b) 較簡潔的程式 LEA EBX,NUM1 MO V ECX,N MO EAX,0 清除累積(EAX)與索引(EDI) 暫存器 MO V EDI,0 ST AR T ADD: ADD EAX,[EBX + EDI * 4] 把下一個數加入 EAX INC EDI 遞增索引暫存器 DEC ECX 遞減計數暫存器 JG ST AR T ADD 若 [ECX] > 0 則跳回 MO V SUM,EAX 把總和存在記憶體 . (a) 直接方式 LEA EBX,NUM1 初始化基底暫存器 EBX 並且讓 它存放 NUM - 4 SUB EBX,4 MO V ECX,N 初始化累積/索引(ECX) MO V EAX,0 清除累積器(EAX) ST AR T ADD: ADD EAX,[EBX + ECX * 4] 把下一個數加入 EAX LOOP ST AR T ADD 遞減 ECX,若 [ECX] > 0 則跳回 MO V SUM,EAX 把總和存在記憶體 (b) 較簡潔的程式 圖 3.40 用來累加數值的 IA-32 程式
(a) 呼叫程式與副常式 (b) 在副常式中儲存 EDI 後的堆疊內容 . . . LEA EBX,NUM1 把參數載入 EBX、ECX MO V ECX,N CALL LIST ADD 跳到副常式 MO V SUM,EAX 把總和存入記憶體 . . . 副常式 LIST ADD: PUSH EDI 儲存 EDI v e MO V EDI,0 使用 EDI 做為索引暫存器 MO V EAX,0 使用 EAX 做為累積暫存器 ST AR T ADD: ADD EAX, [EBX + EDI * 4] 加上下一個數 INC EDI 遞增索引 DEC ECX 遞減計數器 JG STARTADD 若 [ECX] > 0 則跳回 POP EDI 回復 EDI RET 跳回呼叫程式 (a) 呼叫程式與副常式 ESP [EDI] Return Address Old TOS (b) 在副常式中儲存 EDI 後的堆疊內容 圖 3.45 把圖 3.40a 寫成 IA-32 副常式的程式;此程式透過暫存器來傳遞參數
圖 3.46 把圖 3.40a 的程式寫成 IA-32 子常式的程式; 參數透過堆疊來傳遞 (a) 呼叫程式與副常式 (假定堆疊頂端位於以下第一層) 1 呼叫程式 PUSH OFFSET NUM1 把參數推上堆疊 PUSH N CALL LIST ADD 跳到副常式 ADD ESP ,4 從堆疊中移除 n POP SUM 取出總和並放入 SUM . . . 副常式 LIST ADD: PUSH EDI 儲存 EDI 並且用來做為索引暫 存器 e MO V EDI,0 PUSH EAX 儲存 EAX 並且用來做為累積暫 存器 MO V EAX,0 PUSH EBX 儲存 EBX 並且載入位址 NUM1 MO V EBX,[ESP+20] PUSH ECX 儲存 ECX 並且載入計數 n MO V ECX,[ESP+20] ST AR T ADD: ADD EAX,[EBX+EDI * 4] 加上下一個數 INC EDI 遞增索引 DEC ECX 遞減計數器 JG ST AR T ADD 若尚未完成則跳回 MO V [ESP+24],EAX 以總和覆蓋堆疊的 NUM1 POP ECX 回復暫存器 POP EBX POP EAX POP EDI RET 回傳 (a) 呼叫程式與副常式 第三層 [ECX] [EBX] [EAX] [EDI] 第二層 回傳位址 n NUM1 第一層 (b) 不同時期的堆疊內容 圖 3.46 把圖 3.40a 的程式寫成 IA-32 子常式的程式; 參數透過堆疊來傳遞
圖 3.47 IA-32 組合語言的巢狀副常式 記憶體位址 指令 註解 呼叫程式 ... 2000 PUSH PARAM2 把參數放上堆疊 ... 2000 PUSH PARAM2 把參數放上堆疊 2006 PARAM1 2012 CALL SUB1 2017 POP RESULT 儲存結果 ADD ESP,4 回復堆疊層次 第一個子常式 2100 SUB1: EBP 儲存窗格指標暫存器 MOV EBP,ESP 載入窗格指標 EAX 儲存暫存器 EBX ECX EDX EAX,[EBP+8] 取得第一個參數 EBX,[EBP+12] 取得第二個參數 PARAM3 2060 SUB2 2165 取出 SUB2 的結果並放入 ECX [EBP+8],EDX 把答案放上堆疊 回復暫存器 回復窗格指標暫存器 RET 回到主程式 第二個副常式 3000 SUB2: 取得參數 [EBP+8],EBX 把 SUB2 結果放上堆疊 回到第一個子常式 建立sub1的EBP 此時EBP指向[EBP] from Main 圖 3.47 IA-32 組合語言的巢狀副常式
圖 3.48 圖 3.47 的 IA-32 堆疊窗格 [EBX] from SUB1 [EAX] from SUB1 第二個副常式 的堆疊窗格 [EBP] from SUB1 EBP 2165 param3 [EDX] from Main [ECX] from Main [EBX] from Main [EAX] from Main 第一個副常式 的堆疊窗格 [EBP] from Main EBP 2017 param1 param2 舊的 TOS 圖 3.48 圖 3.47 的 IA-32 堆疊窗格
圖 3.50 使用直接選擇排序之 IA-32 版本的位元組排序程式 for (j = n – 1; j > 0; j = – j 1) { for ( k = – j 1; k > = 0; k = k – 1 ) { if (LIST[ k ] > LIST[ j ]) { TEMP = LIST[ k ]; LIST[ k ] = LIST[ j ]; LIST[ j ] = TEMP; } } } (a) 排序的 C 語言程式 LEA EAX,LIST 載入串列指標的基底暫存器 (EAX), 把外部迴圈的索引暫存器(EDI)初始 化為 j = n - 1 MO V EDI,N DEC EDI OUTER: MO V ECX,EDI 把內部迴圈的索引暫存器 (ECX)初始 化為 k = j - 1 DEC ECX MO V DL,[EAX + EDI] 把 LIST(j) 載入暫存器 DL INNER: CMP [EAX + ECX],DL 比較 LIST(k) 跟 LIST(j) JLE NEXT 若LIST(k)≤ LIST(j)則跳到下一個較 小的 k 索引項目; X CHG [EAX + ECX],DL 否則,交換LIST(k)與LIST(j),並且 把新的 LIST(j) 留在 DL MO V [EAX + EDI],DL NEXT: DEC ECX 遞減內部迴圈索引 k JGE INNER 重複或結束內部迴圈 DEC EDI 遞減外部迴圈索引 j JG OUTER 重複或結束外部迴圈 (b) IA-32 程式的實作 圖 3.50 使用直接選擇排序之 IA-32 版本的位元組排序程式
表 3.1 ARM 的索引定址模式 名稱 組譯程式語法 定址函數 包含立即偏移量: 前置索引 [Rn,#offset] EA = [Rn] + offset 包含寫回的前置索引 [Rn,#offset]! EA = [Rn] + offset; Rn ← [Rn] + offset 後置索引 [Rn],#offset EA = [Rn]; 在 Rm 中包含偏移量大小: [Rn,±Rm,shift] EA = [Rn]±[Rm]移位 [Rn,±Rm,shift]! EA = [Rn]±[Rm]移位; Rn ← [Rn]±[Rm]移位 [Rn],±Rm,shift 相對(包含立即偏移量的前置索引) Location EA = Location = [PC] + offset EA = 有效位址 offset = 位於指令中的有號數 shift = 有向整數,其中左移的方向為 LSL,或是右移的方向為 LSR,整數 為用來指定移位量的 5 位元無號數 ±Rm = 位於暫存器 Rm 中,可以被加入基底暫存器 Rn ,或是減去 Rn 的偏移量大小
表 3.2 68000 定址模式 名稱 組譯程式語法 定址函數 立即 #Value 運算元 = Value 絕對短 Value 表 3.2 68000 定址模式 名稱 組譯程式語法 定址函數 立即 #Value 運算元 = Value 絕對短 Value EA = 以正負號延伸的 WValue 絕對長 EA = Value 暫存器 Rn EA = Rn, 也就是運算元 = [Rn] 暫存器間接 (An) EA = [An] 自動遞增 (An)+ EA = [An]; 遞增 An 自動遞減 -(An) 遞減 An; 索引基本 WValue(An) EA = WValue + [An] 索引完整 BValue(An,Rk.S) EA = BValue + [An] + [Rk] 相對基本 WValue(PC) 或 Label EA = WValue + [PC] 相對完整 或 Label(Rk) EA = BValue + [PC] + [Rk] EA = 有效位址 Value = 明確給定的數,或是以標記表示的數 BValue = 8 位元的 Value WValue = 16 位元的 Value An = 位址暫存器 Rn = 位址或資料暫存器 S = 大小指示子:W 表示以正負號延伸的 16 位元字組, L 表示 32 位元的長字組
表 3.3 IA-32 的定址模式 名稱 組譯程式語法 定址函數 立即 Value 運算元 = Value 直接 Location EA = Location 暫存器 Reg EA = Reg, 也就是運算元 = [Reg] 暫存器間接 [Reg] EA = [Reg] 包含位移量的基底 [Reg + Disp] EA = [Reg] + Disp 包含位移量的索引 [Reg * S + Disp] EA = [Reg] × S + Disp 包含索引的基底 [Reg1 + Reg2 * S] EA = [Reg1] + [Reg2] × S 包含索引與位移量的索引 [Reg1 + Reg2 * S + Disp] EA = [Reg1] + [Reg2] × S + Disp Value = 8 位元或 32 位元的有號數 Location = 32 位元位址 Reg,Reg1,Reg2 = 通用暫存器 EAX、EBX、ECX、EDX、ESP、EBP、ESI、 EDI 之一,其中 ESP 無法被用於索引暫存器 Disp = 8 位元或 32 位元的有號數,其中在包含位移量的索引模式 中只能使用 32 位元。 S =縮放因子 1、2、4、或 8
結論 RISC ARM(Advanced RISC Machines Limited,Acorn Computers Company) Support both big-endian and little-endian Opcode dst,src CISC 68000 (Motorola Processor) Big-endian 例如12345678h在記憶體擺放為 Opcode src,dst IA-32 (Intel Architecture-32 bits) Little-endian