Tôi đã thử nghiệm một chút với việc thực thi từ RAM và bộ nhớ flash trên các hệ thống nhúng. Để tạo mẫu và thử nghiệm nhanh, tôi hiện đang sử dụng Arduino Do (SAM3X8E ARM Cortex-M3). Theo như tôi có thể thấy, bộ thực thi và bộ nạp khởi động Arduino sẽ không có sự khác biệt nào ở đây.
Đây là vấn đề: Tôi có một hàm ( calc ) được viết trong ARM Thumb hội. calc tính một số và trả về nó. (Thời gian chạy> 1 giây cho đầu vào đã cho) Bây giờ tôi đã trích xuất thủ công mã máy đã lắp ráp của hàm đó và đặt nó dưới dạng byte thô vào hàm khác. Cả hai chức năng được xác nhận nằm trong bộ nhớ flash (Địa chỉ 0x80149 và 0x8017D, ngay cạnh nhau). Điều này đã được xác nhận cả thông qua việc tháo gỡ và kiểm tra thời gian chạy.
void setup() {
Serial.begin(115200);
timeFnc(calc);
timeFnc(calc2);
}
void timeFnc(int (*functionPtr)(void)) {
unsigned long time1 = micros();
int res = (*functionPtr)();
unsigned long time2 = micros();
Serial.print("Address: ");
Serial.print((unsigned int)functionPtr);
Serial.print(" Res: ");
Serial.print(res);
Serial.print(": ");
Serial.print(time2-time1);
Serial.println("us");
}
int calc() {
asm volatile(
"movs r1, #33 \n\t"
"push {r1,r4,r5,lr} \n\t"
"bl .in \n\t"
"pop {r1,r4,r5,lr} \n\t"
"bx lr \n\t"
".in: \n\t"
"movs r5,#1 \n\t"
"subs r1, r1, #1 \n\t"
"cmp r1, #2 \n\t"
"blo .lblb \n\t"
"movs r5,#1 \n\t"
".lbla: \n\t"
"push {r1, r5, lr} \n\t"
"bl .in \n\t"
"pop {r1, r5, lr} \n\t"
"adds r5,r0 \n\t"
"subs r1,#2 \n\t"
"cmp r1,#1 \n\t"
"bhi .lbla \n\t"
".lblb: \n\t"
"movs r0,r5 \n\t"
"bx lr \n\t"
::
); //redundant auto generated bx lr, aware of that
}
int calc2() {
asm volatile(
".word 0xB5322121 \n\t"
".word 0xF803F000 \n\t"
".word 0x4032E8BD \n\t"
".word 0x25014770 \n\t"
".word 0x29023901 \n\t"
".word 0x800BF0C0 \n\t"
".word 0xB5222501 \n\t"
".word 0xFFF7F7FF \n\t"
".word 0x4022E8BD \n\t"
".word 0x3902182D \n\t"
".word 0xF63F2901 \n\t"
".word 0x0028AFF6 \n\t"
".word 0x47704770 \n\t"
);
}
void loop() {
}
Đầu ra của chương trình trên trên mục tiêu Arduino Do là:
Address: 524617 Res: 3524578: 1338254us
Address: 524669 Res: 3524578: 2058819us
Vì vậy, chúng tôi xác nhận kết quả là bằng nhau và địa chỉ trong thời gian chạy là như mong đợi. Thực thi chức năng mã máy được nhập thủ công chậm hơn 50%.
Việc tháo gỡ với arm-none-eabi-objdump xác nhận thêm các địa chỉ tương ứng, cư trú bộ nhớ flash và tính công bằng của mã máy (Lưu ý về tuổi thọ và nhóm byte!):
00080148 <_Z4calcv>:
80148: 2121 movs r1, #33 ; 0x21
8014a: b532 push {r1, r4, r5, lr}
8014c: f000 f803 bl 80156 <.in>
80150: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr}
80154: 4770 bx lr
00080156 <.in>:
80156: 2501 movs r5, #1
80158: 3901 subs r1, #1
8015a: 2902 cmp r1, #2
8015c: f0c0 800b bcc.w 80176 <.lblb>
80160: 2501 movs r5, #1
00080162 <.lbla>:
80162: b522 push {r1, r5, lr}
80164: f7ff fff7 bl 80156 <.in>
80168: e8bd 4022 ldmia.w sp!, {r1, r5, lr}
8016c: 182d adds r5, r5, r0
8016e: 3902 subs r1, #2
80170: 2901 cmp r1, #1
80172: f63f aff6 bhi.w 80162 <.lbla>
00080176 <.lblb>:
80176: 0028 movs r0, r5
80178: 4770 bx lr
}
8017a: 4770 bx lr
0008017c <_Z5calc2v>:
8017c: b5322121 .word 0xb5322121
80180: f803f000 .word 0xf803f000
80184: 4032e8bd .word 0x4032e8bd
80188: 25014770 .word 0x25014770
8018c: 29023901 .word 0x29023901
80190: 800bf0c0 .word 0x800bf0c0
80194: b5222501 .word 0xb5222501
80198: fff7f7ff .word 0xfff7f7ff
8019c: 4022e8bd .word 0x4022e8bd
801a0: 3902182d .word 0x3902182d
801a4: f63f2901 .word 0xf63f2901
801a8: 0028aff6 .word 0x0028aff6
801ac: 47704770 .word 0x47704770
}
801b0: 4770 bx lr
...
Chúng ta có thể xác nhận thêm quy ước gọi được sử dụng tương tự:
00080234 <setup>:
void setup() {
80234: b508 push {r3, lr}
Serial.begin(115200);
80236: 4806 ldr r0, [pc, #24] ; (80250 <setup+0x1c>)
80238: f44f 31e1 mov.w r1, #115200 ; 0x1c200
8023c: f000 fcb4 bl 80ba8 <_ZN9UARTClass5beginEm>
timeFnc(calc);
80240: 4804 ldr r0, [pc, #16] ; (80254 <setup+0x20>)
80242: f7ff ffb7 bl 801b4 <_Z7timeFncPFivE>
}
80246: e8bd 4008 ldmia.w sp!, {r3, lr}
timeFnc(calc2);
8024a: 4803 ldr r0, [pc, #12] ; (80258 <setup+0x24>)
8024c: f7ff bfb2 b.w 801b4 <_Z7timeFncPFivE>
80250: 200705cc .word 0x200705cc
80254: 00080149 .word 0x00080149
80258: 0008017d .word 0x0008017d
Tôi có thể loại trừ trường hợp này do một số loại tìm nạp đầu cơ (mà Cortex-M3 dường như có!) Hoặc bị gián đoạn. (EDIT: NOPE, tôi không thể. Có lẽ một số loại tìm nạp trước) Thay đổi thứ tự thực hiện hoặc thêm các lệnh gọi hàm ở giữa không thay đổi kết quả. Điều gì có thể là thủ phạm ở đây?
EDIT: Sau khi thay đổi căn chỉnh của chức năng mã máy (chèn nops làm phần mở đầu) Tôi nhận được các kết quả sau:
+ 16 bit cho calc2:
Address: 524617 Res: 3524578: 1102257us
Address: 524669 Res: 3524578: 1846968us
+ 32 bit cho calc2:
Address: 524617 Res: 3524578: 1102257us
Address: 524669 Res: 3524578: 1535424us
+ 48 bit cho calc2:
Address: 524617 Res: 3524578: 1102155us
Address: 524669 Res: 3524578: 1413180us
+ 64 bit cho calc2:
Address: 524617 Res: 3524578: 1102155us
Address: 524669 Res: 3524578: 1346606us
+ 80 bit cho calc2:
Address: 524617 Res: 3524578: 1102145us
Address: 524669 Res: 3524578: 1180105us
EDIT2: Chỉ chạy calc:
Address: 524617 Res: 3524578: 1102155us
Chỉ chạy calc2:
Address: 524617 Res: 3524578: 1102257us
Thay đổi thứ tự:
Address: 524669 Res: 3524578: 1554160us
Address: 524617 Res: 3524578: 1102211us
EDIT3: Thêm .p2align 4
trước nhãn chỉ .in
cho calc, thực hiện riêng:
Address: 524625 Res: 3524578: 1413185us
Cả hai như trong điểm chuẩn ban đầu:
Address: 524625 Res: 3524578: 1413185us
Address: 524689 Res: 3524578: 1535424us
EDIT4: Đảo ngược vị trí trong flash thay đổi hoàn toàn kết quả. -> Tìm nạp trước tuyến tính?