2013-03-27 30 views
5

Tôi có mã khởi động cho ARM bằng kim loại trần được viết bằng lắp ráp và tôi đang cố gắng hiểu cách hoạt động của nó. Mã nhị phân được viết bằng một số Flash bên ngoài và đang sao chép các phần của chính nó trong RAM khi khởi động. Tôi vẫn không chính xác nhận được khái niệm di dời trong bối cảnh này, mặc dù tôi đọc số wikipedia entry này. RAM được ánh xạ tới cửa sổ địa chỉ thấp và đèn flash trong cửa sổ địa chỉ cao. Ai đó có thể giải thích cho tôi tại sao chúng tôi kiểm tra giá trị của thanh ghi liên kết tại đây?Tái định cư trong lắp ráp

/* Test if we are running from an address, we are not linked at */ 
     bl check_position 
check_position: 
     mov  r0, lr     
     ldr  r1, =check_position 
     cmp  r0, r1     /* ; don't relocate during debug */ 
     beq  relocated_entry 
+0

Cảm ơn bạn đã có hai câu trả lời tuyệt vời! Tôi sẽ chấp nhận cả hai nếu tôi coud, vì một trong những giải thích mục tiêu của mã (giả định chương trình loader JTAG là đúng) và thứ hai làm thế nào nó hoạt động chính xác. –

Trả lời

5

tôi đoán là ứng dụng chạy từ ram, và khi gỡ lỗi các ứng dụng giả này có lẽ là sử dụng một số loại bootloader và hay jtag để tải ứng dụng thử nghiệm trực tiếp vào ram, do đó không có lý do gì để sao chép và chạy (có thể gây ra sự cố).

Một lý do khác khiến bạn làm như thế này là tránh vòng lặp vô hạn. Nếu ví dụ bạn muốn khởi động từ flash (phải thường) nhưng thực hiện từ ram, cách đơn giản nhất để làm điều đó là chỉ cần sao chép toàn bộ flash hoặc toàn bộ một số đoạn flash vào ram và chỉ nhánh vào đầu ram. Mà khi bạn làm điều đó có nghĩa là bạn nhấn nút "sao chép ứng dụng vào ram và nhánh" một lần nữa, để tránh nó lần thứ hai (có thể làm hỏng bạn), bạn có một số loại tôi đang chạy vòng lặp này từ flash hoặc không kiểm tra.

3

Bất cứ ai có thể giải thích cho tôi lý do chúng tôi kiểm tra giá trị của thanh ghi liên kết tại đây không?

Các bl check_position sẽ đặt giá trị của PC+4 trong liên kết đăng ký và chuyển điều khiển đến đoạn check_position tương đối cũng PC. bl at ARM Cho đến nay mọi thứ đều là PC tương đối.

ldr r1,=check_position nhận giá trị từ hồ bơi theo nghĩa đen. Ref1 Mã thực tế có vẻ như,

ldr r1,[pc, #offset] 
... 
    offset: 
    .long check_position # absolute address from assemble/link. 

Vì vậy, các R0 chứa một phiên bản máy tính tương đối và các R1 chứa phiên bản lắp ráp tuyệt đối. Ở đây, chúng được so sánh. Bạn cũng có thể sử dụng số học để tính toán sự khác biệt và sau đó chi nhánh cho nó nếu khác không; hoặc có thể sao chép mã đến đích tuyệt đối của nó. Ref2 Nếu mã là chạy tại địa chỉ được liên kết, sau đó R0R1 giống nhau. Đây là một số pseudo code cho bl.

mov lr,pc    ; pc is actually two instruction ahead. 
add pc,pc,#branch_offset-8 

Điều quan trọng là BL làm mọi thứ dựa trên PC bao gồm bản cập nhật của lr. Thay vì sử dụng thủ thuật này, chúng tôi có thể sử dụng mov R0,PC, ngoại trừ PC là 8 byte phía trước. Một giải pháp thay thế khác là sử dụng adr R0,check_position, điều này sẽ giúp người lắp ráp thực hiện tất cả các phép toán địa chỉ cho chúng ta.

/* Test if we are running from an address, we are not linked at */ 
check_position: 
    adr r0, check_position 
    ldr r1, =check_position 
    cmp r0, r1     /* ; don't relocate during debug */ 
    beq relocated_entry 

Ref1: Xem Arm op-codes.ltorg trong gnu-lắp ráp thủ công
Ref2: Đây là chính xác những gì Linux head.S đang làm cho ARM.

Chỉnh sửa: Tôi đã kiểm tra ARM ARM và PC rõ ràng là hướng dẫn hiện tại +8, hiển thị tại sao mã như thế này. Tôi nghĩ rằng phiên bản adr trực quan và dễ đọc hơn, nhưng không thể sử dụng giả adr thường xuyên để mọi người có thể không quen thuộc với nó.