Bài giảng Vi xử lý nâng cao - Phần 1: Thiết kế CPU RISC - Bài 16: Hợp ngữ và C của Intel Xscale®
Phác thảo bài học
. Mô hình đối với người lập trình của Intel
Xscale®.
. Giới thiệu hợp ngữ của Intel Xscale®.
. Mã hợp ngữ từ các chương trình C (7 thí
dụ).
. Xử lý các cấu trúc.
. Giao diện mã C với hợp ngữ của Intel
Xscale®.
. Các thư viện của Intel Xscale® và arm
. Mô hình đối với người lập trình của Intel
Xscale®.
. Giới thiệu hợp ngữ của Intel Xscale®.
. Mã hợp ngữ từ các chương trình C (7 thí
dụ).
. Xử lý các cấu trúc.
. Giao diện mã C với hợp ngữ của Intel
Xscale®.
. Các thư viện của Intel Xscale® và arm
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Vi xử lý nâng cao - Phần 1: Thiết kế CPU RISC - Bài 16: Hợp ngữ và C của Intel Xscale®", để tải tài liệu gốc về máy hãy click vào nút Download ở trên.
File đính kèm:
- bai_giang_vi_xu_ly_nang_cao_phan_1_thiet_ke_cpu_risc_bai_16.pdf
- Lec16.ppt
Nội dung text: Bài giảng Vi xử lý nâng cao - Phần 1: Thiết kế CPU RISC - Bài 16: Hợp ngữ và C của Intel Xscale®
- Bài giảng “Vi xử lý nâng cao” Phần 3: Giới thiệu chip ARM Bài 16: Hợp ngữ và C của Intel Xscale® Giới thiệu hệ thống nhúng 1
- Các tài liệu tham khảo • Các tài liệu của môn học Các bản tin của Lab Tài liệu về XScale Tài liệu về ARM. Sách chỉ dẫn trình dịch hợp ngữ (Assembler Guide). Sách chỉ dẫn CodeWarrior IDE (CodeWarrior IDE Guide). Sách tham khảo kiến trúc ARM (ARM Architecture Reference Manual). Bộ tài liệu của người phát triển ARM: Bắt đầu (ARM Developer Suite: Getting Started). Giới thiệu hệ thống nhúng 3
- Mô hình đối với người lập trình của Intel Xscale® (2) • Tập thanh ghi của Intel Xscale® – Các thanh ghi R0-R15 + CPSR (T/ghi trạng thái c/trình hiện hành). – R13 : Con trỏ stack (Stack Pointer). – R14 : Thanh ghi liên kết (Link Register). – R15 : Bộ đếm chương trình (Program Counter), bỏ qua các bit 0:1 . • Các thanh ghi trạng thái chương trình – CPSR (Thanh ghi trạng thái chương trình hiện hành) • lưu thông tin về hoạt động được thực hiện gần nhất của ALU. – chứa các bit N (negative), Z (zero), C (Carry) và V (oVerflow). • điều khiển cho phép và không cho phép các ngắt. • thiết lập chế độ hoạt động của bộ xử lý. – SPSR (Thanh ghi trạng thái chương trình được lưu) • được sử dụng bởi các trình xử lý ngoại lệ. • Các ngoại lệ – reset , lệnh chưa định nghĩa , SWI, IRQ. Giới thiệu hệ thống nhúng 5
- Cấu trúc của mô-đun hợp ngữ Nhóm mã hoặc dữ liệu được quản lý bởi trình liên kết Khối được yêu cầu tối thiểu (tại sao?) AREA Example, CODE, READONLY ; tên của khối mã. Lệnh đầu ENTRY ; lệnh thực thi đầu tiên. tiên được start thực thi MOV r0, #15 ; thiết lập các thông số. MOV r1, #20 BL func ; gọi chương trình con. SWI 0x11 ; kết thúc chương trình. func ; chương trình con. ADD r0, r0, r1 ; r0 = r0 + r1 MOV pc, lr ; trở về từ chương trình con. ; kết quả trong r0. END ; kết thúc mã. Giới thiệu hệ thống nhúng 7
- Tạo mã hợp ngữ từ C • Sử dụng tùy chọn dòng lệnh –S trong các tính chất “đích” của Code Warrior. – Khi ta biên dịch tập tin .c, ta được tập tin .s. – Tập tin .s này chứa mã hợp ngữ được tạo ra bởi trình biên dịch. • Khi được hợp dịch, mã này có khả năng được liên kết và được nạp thành tập tin thi hành được. Giới thiệu hệ thống nhúng 9
- Thí dụ 1 (tiếp theo) address AREA ||.text||, CODE, READONLY main PROC |L1.0| 0x00000000 LDR r0,|L1.28| 0x00000004 MOV r1,#3 0x00000008 STR r1,[r0,#0] ; a 0x0000000C MOV r1,#4 0x00000010 STR r1,[r0,#4] ; b 0x00000014 MOV r0,#0 0x00000018 BX lr // gọi chương trình con 0x0000001C |L1.28| DCD 0x00000020 Đây là con trỏ “trỏ ENDP đến” |x$dataseg|. AREA ||.bss|| a ||.bss$2|| 0x00000020 DCD 00000000 b 0x00000024 DCD 00000000 EXPORT main EXPORT b EXPORT a END Giới thiệu hệ thống nhúng 11
- Thí dụ 2: Gọi hàm int tmp; AREA ||.text||, CODE, READONLY swap PROC void swap(int a, int b); LDR r2,|L1.56| int main() STR r0,[r2,#0] ; tmp { MOV r0,r1 int a,b; LDR r2,|L1.56| a = 3; LDR r1,[r2,#0] ; tmp BX lr b = 4; main PROC STMFD store multiple, swap(a,b); STMFD sp!,{r4,lr} full descending } /* end main() */ MOV r3,#3 sp sp 4 MOV r4,#4 mem[sp] = lr ; linkreg sp sp – 4 void swap(int a,int b) MOV r1,r4 MOV r0,r3 mem[sp] = r4 ; linkreg { BL swap tmp = a; MOV r0,#0 a = b; LDMFD sp!,{r4,pc} b = tmp; |L1.56| DCD ||.bss$2|| ; trỏ đến tmp END } /* end swap() */ contents of lr Content: nội dung SP contents of r4 Giới thiệu hệ thống nhúng 13
- Thí dụ 3: Quản lý các con trỏ int tmp; AREA ||.text||, CODE, READONLY int *pa, *pb; swap LDR r1,|L1.60| ; get tmp addr STR r0,[r1,#0] ; tmp = a void swap(int a, int b); BX lr int main() main STMFD sp!,{r2,r3,lr} { LDR r0,|L1.60| ; get tmp addr int a,b; ADD r1,sp,#4 ; &a on stack pa = &a; STR r1,[r0,#4] ; pa = &a STR sp,[r0,#8] ; pb = &b (sp) pb = &b; MOV r0,#3 *pa = 3; STR r0,[sp,#4] ; *pa = 3 *pb = 4; MOV r1,#4 swap(*pa, *pb); STR r1,[sp,#0] ; *pb = 4 } /* end main() */ BL swap ; call swap MOV r0,#0 LDMFD sp!,{r2,r3,pc} void swap(int a,int b) |L1.60| DCD ||.bss$2|| { AREA ||.bss|| tmp = a; ||.bss$2|| a = b; tmp DCD 00000000 pa DCD 00000000 b = tmp; pb DCD 00000000 } /* end swap() */ Giới thiệu hệ thống nhúng 15
- Ghi chú cho thí dụ 3 • |L1.60| chứa địa chỉ của tmp. • a và b là các biến cục bộ được lưu ở các vị trí nhớ sp+4 và sp theo thứ tự trong main(). • pa và pb là các biến toàn cục được tính như là các offset từ &tmp (pa=&tmp+4, pb=&tmp+8). • pa được thiết lập đến &a. • pb được thiết lập đến &b. • Vì a và b bị thay đổi nhưng không được sử dụng lần nữa trong swap(), mã bị loại bỏ bởi trình biên dịch nên swap() chỉ chứa tmp=a. Giới thiệu hệ thống nhúng 17
- Ghi chú cho thí dụ 4 • |L1.56| là con trỏ đến cấu trúc, con trỏ này được lưu trong r1. • Các phần tử của cấu trúc được truy cập dưới dạng các offset từ r1. – e.g. STR r0,[r1,#4] ; ptest->b = 10 Giới thiệu hệ thống nhúng 19
- Content: nội dung. Thí dụ 5 (tiếp theo) 1 address contents of lr AREA ||.text||, CODE, READONLY 0x90 test LDR r1,[sp,#0] ; get &e contents of r3 0x8c LDR r2,|L1.72| ; get tmp addr contents of r2 STR r0,[r2,#0] ; tmp = a SP 0x88 STR r3,[r1,#0] ; *e = d 0x84 BX lr 0x80 main PROC STMFD sp!,{r2,r3,lr} ; 2 slots 1 MOV r0,#3 ; 1st param a MOV r1,#4 ; 2nd param b 2 address MOV r2,#5 ; 3rd param c 0x90 MOV r12,#6 ; 4th param d #7 0x8c MOV r3,#7 ; overflow stack 0x88 STR r3,[sp,#4] ; e on stack 2 SP ADD r3,sp,#4 0x84 STR r3,[sp,#0] ; &e on stack 3 0x80 MOV r3,r12 ; 4th param d in r3 BL test MOV r0,#0 3 address LDMFD sp!,{r2,r3,pc} 0x90 |L1.72| DCD ||.bss$2|| #7 0x8c tmp Lưu ý: Trong “test”, trình biên dịch SP 0x8c 0x88 loại bỏ các phép gán đến a, b và c 0x84 các phép gán này không có ảnh 0x80 hưởng , do vậy chúng được bỏ qua. Giới thiệu hệ thống nhúng 21
- Thí dụ 6: Các lời gọi hàm lồng nhau int tmp; swap2 LDR r1,|L1.72| int swap(int a, int b); STR r0,[r1,#0] ; tmp a void swap2(int a, int b); BX lr int main(){ swap MOV r2,r0 ; r2=a int a, b, c; MOV r0,r1 ; a=b (r0=b) a = 3; STR lr,[sp,#-4]! ; save lr b = 4; LDR r1,|L1.72| c = swap(a,b); STR r2,[r1,#0] ; tmp=a } /* end main() */ MOV r1,r2 ; r1=tmp BL swap2 ; call swap2 int swap(int a,int b){ MOV r0,#0xa ; ret value tmp = a; LDR pc,[sp],#4 ; restore lr a = b; main STR lr,[sp,#-4]! b = tmp; MOV r0,#3 ; set up params swap2(a,b); MOV r1,#4 ; before call return(10); BL swap ; to swap } /* end swap() */ MOV r0,#0 LDR pc,[sp],#4 void swap2(int a,int b){ |L1.72| tmp = a; DCD ||.bss$2|| a = b; AREA ||.bss||, NOINIT, ALIGN=2 b = tmp; tmp } /* end swap() */ Giới thiệu hệ thống nhúng 23
- Thí dụ 7: Tối ưu hóa ngang qua các hàm int tmp; AREA ||.text||, CODE, READONLY int swap(int a,int b); swap2 LDR r1,|L1.60| void swap2(int a,int b); STR r0,[r1,#0] ; tmp BX lr int main(){ Không trở về swap() , swap MOV r2,r0 thay vào đó nhảy trực int a, b, c; MOV r0,r1 tiếp trở về main() a = 3; LDR r1,|L1.60| b = 4; STR r2,[r1,#0] ; tmp c = swap(a,b); MOV r1,r2 B swap2 ; *NOT* “BL” } /* end main() */ main PROC int swap(int a,int b){ STR lr,[sp,#-4]! tmp = a; MOV r0,#3 a = b; MOV r1,#4 b = tmp; BL swap MOV r0,#0 swap2(a,b); LDR pc,[sp],#4 } /* end swap() */ |L1.60| void swap2(int a,int b){ DCD ||.bss$2|| tmp = a; AREA ||.bss||, tmp a = b; ||.bss$2|| % 4 b = tmp; So sánh với Example 6 trong thí dụ này , trình dịch tối ưu hóa mã sao cho } /* end swap() */ swap2() trực tiếp trở về main(). Giới thiệu hệ thống nhúng 25
- Giao diện C và hợp ngữ • ARM ( công ty @ www.arm.com) đã phát triển một chuẩn gọi là“Chuẩn gọi thủ tục ARM” (APCS) , chuẩn này định nghĩa: – các ràng buộc về cách sử dụng các thanh ghi. – các qui ước của stack. – khuôn dạng cấu trúc dữ liệu backtrace của stack. – việc truyền đối số và trả về kết quả. – hỗ trợ ARM dùng chung cơ chế thư viện. • Mã tạo ra bởi trình biên dịch tuân theo APCS – Đây chỉ là một chuẩn không phải yêu cầu thuộc kiến trúc. – Không thể bỏ qua chuẩn khi giao diện C và mã hợp ngữ. – Có thể bỏ qua chuẩn khi chỉ viết mã hợp ngữ hoặc khi viết mã hợp ngữ không được gọi bởi mã C. Giới thiệu hệ thống nhúng 27
- STM đặt các thứ vào trong bộ nhớ ra sao ? STM sp!, {r0r15} address SP trước 0x90 • Bộ xử lý XScale sử dụng pc 0x8c bit-vector để biểu diễn lr 0x88 từng thanh ghi được lưu. sp 0x84 ip 0x80 • Kiến trúc này đặt thanh fp 0x7c ghi số thấp nhất vào địa v7 0x78 chỉ thấp nhất. v6 0x74 v5 0x70 • Mặc định STM == v4 0x6c STMDB v3 0x68 v2 0x64 v1 0x60 a4 0x5c a3 0x58 a2 0x54 a1 0x50 SP sau Giới thiệu hệ thống nhúng 29
- Thí dụ: Truyền cấu trúc như con trỏ typedef struct two_ch_struct{ max PROC char ch1; STMFD sp!,{r0,r1,lr} char ch2; SUB sp,sp,#4 } two_ch; LDRB r0,[sp,#4] LDRB r1,[sp,#8] two_ch max(two_ch a, two_ch b){ CMP r0,r1 return((a.ch1 > b.ch1) ? a : b); BLS |L1.36| LDR r0,[sp,#4] } /* end max() */ STR r0,[sp,#0] B |L1.44| |L1.36| LDR r0,[sp,#8] STR r0,[sp,#0] |L1.44| LDR r0,[sp,#0] LDMFD sp!,{r1-r3,pc} ENDP Giới thiệu hệ thống nhúng 31
- Con trỏ khung (frame pointer) address SP trước 0x90 • fp trỏ tới đỉnh của vùng stack đối pc FP sau 0x8c với hàm hiện hành lr 0x88 – Hoặc zero nếu không được sử dụng. sb 0x84 • Bằng cách sử dụng con trỏ khung ip 0x80 và lưu con trỏ fp này ở cùng offset fp 0x7c đối với mỗi lời gọi hàm, fp tạo ra v7 0x78 danh sách liên kết từng cái một của v6 0x74 các bản ghi kích hoạt (activation v5 0x70 records). v4 0x6c v3 0x68 • Tạo ra cấu trúc “backtrace ” của v2 0x64 stack . v1 0x60 MOV ip, sp a4 0x5c STMFD sp!,{a1a4,v1- a3 0x58 v5,sb,fp,ip,lr,pc} a2 0x54 SUB fp, ip, #4 a1 0x50 SP sau Giới thiệu hệ thống nhúng 33
- Nhân • Lệnh nhân có thể chiếm nhiều chu kỳ. – Có thể biến đổi (Y * Hằng số) thành chuỗi phép cộng và dịch. – Y * 9 = Y * 8 + Y * 1 – Giả định R1 lưu Y và R2 sẽ lưu kết quả. ADD R2, R2, R1, LSL #3 ; nhân với 9 (Y * 8) + (Y * 1) RSB R2, R1, R1, LSL #3 ; nhân với 7 (Y * 8) - (Y * 1) (RSB: phép trừ ngược – các toán hạng của phép trừ bị đảo) • Thí dụ khác : Y * 105 – 105 = 128 23 = 128 (16 + 7) = 128 (16 + (8 1)) RSB r2, r1, r1, LSL #3 ; r2 < Y*7 = Y*8 Y*1( giả định r1 lưu Y). ADD r2, r2, r1, LSL #4 ; r2 < r2 + Y * 16 (r2 đã lưu Y*7; lúc này lưu Y*23). RSB r2, r2, r1, LSL #7 ; r2 < (Y * 128) r2 (r2 lúc này lưu Y*105). • Hoặc Y * 105 = Y * (15 * 7) = Y * (16 1) * (8 1) RSB r2,r1,r1,LSL #4 ; r2 < (r1 * 16) r1 RSB r3, r2, r2, LSL #3 ; r3 < (r2 * 8) r2 Giới thiệu hệ thống nhúng 35