2012-01-21 40 views
7

Tôi đang cố gắng thực hiện một số chương trình trần kim loại trong ARM với GCC và thử nghiệm trên QEMU. Bất cứ khi nào tôi gọi vào một nhãn ARM từ C, chương trình của tôi bị treo. Tôi có một ví dụ đơn giản của mã cho thấy vấn đề tại https://gist.github.com/1654392 - khi tôi gọi kích hoạt() trong mã đó, nó bị treo.Gọi lắp ráp ARM từ C, GCC (kim loại trần)

Tôi đã quan sát với objdump rằng khi tôi làm một bl từ lắp ráp để mã C (như từ _start) nó được tạo ra một wrapper nhỏ chuyển sang hướng dẫn ngón tay cái. Có vẻ như mã C là tất cả được tạo ra trong hướng dẫn ngón tay cái, nhưng tất cả các hội đồng của tôi đang được tạo ra trong ARM (32-bit) hướng dẫn. Tôi không thể hiểu tại sao điều này là hoặc làm thế nào để sửa chữa nó.

+0

nơi là biên dịch này từ đâu? –

+0

kernel.o: (. ARM.exidx + 0x0): undefined tham chiếu đến '__aeabi_unwind_cpp_pr1 ' make: *** [kernel.elf] Lỗi 1 –

+0

bạn đang cố xây dựng một ứng dụng Linux cánh tay? hoặc ứng dụng nhúng (không có hệ điều hành)? nếu một ứng dụng Linux thì bạn không cần mã khởi động toolchain nên làm tất cả điều đó cho bạn, bạn lo lắng về main() làm điểm vào của bạn. –

Trả lời

5

Để gọi chức năng chế độ ARM được định nghĩa trong assembly từ chức năng chế độ THUMB được định nghĩa trong C, bạn cần xác định biểu tượng trong assembly như một hàm và các công cụ (Linaro gcc) sẽ tạo ra lệnh blx thay vì bl.

Ví dụ:

@ Here, we suppose that this part of code is inside of .code 32 

.type fn, %function 

fn: 
    mov pc, lr 
+0

Cảm ơn bạn!Điều này có vẻ hoạt động hoàn hảo và cho phép tôi liên kết trong mã thư viện! – singpolyma

3

xem http://github.com/dwelch67/yagbat thư mục qemu.

Dưới đây là một vài ví dụ về gọi cánh tay hoặc ngón tay cái từ cánh tay

start_vector: 
    mov sp,#0x20000 
    ;@ call an arm function from arm 
    bl notmain 

    ;@ call a thumb function frm arm 
    ldr r0,=0xAABBAABB 
    bl hexstring_trampoline 

    ;@ call a thumb function frm arm 
    ldr r0,=0x12341234 
    ldr r1,hexstring_addr 
    mov lr,pc 
    bx r1 

    ;@ call a thumb function frm arm 
    ldr r0,=0x12312344 
    bl hexstring_trampoline 

hang: 
    b hang 

hexstring_trampoline: 
    ldr r1,hexstring_addr 
    bx r1 

hexstring_addr: .word hexstring 

Nếu bạn nhìn vào các tài liệu tham khảo hướng dẫn thiết lập bạn sẽ thấy rằng bạn cần phải sử dụng BX hay BLX để chuyển qua lại giữa cánh tay và ngón tay cái bang . BLX không được hỗ trợ rộng rãi như BX.

Từ quan điểm định nghĩa, bộ đếm chương trình, máy tính là hai hướng dẫn trước trong khi thực hiện lệnh. cho ngón tay cái đó là 4 byte, cho cánh tay 8 byte. Hoặc là hai trường hợp hướng dẫn. Để mô phỏng một bl mà không thể được sử dụng để thay đổi trạng thái, bạn cần phải tải thanh ghi liên kết với địa chỉ trả về, và sử dụng một bx để nhánh tới trạng thái thay đổi chức năng tùy thuộc vào lsbit của địa chỉ. do đó,

mov lr,pc 
bx r1 
here: 

mov lr, pc above tải địa chỉ ở đây: đó là địa chỉ trả về của chúng tôi, bx r1 theo cách độc lập của nhà nước gọi hàm. các lsbit của địa chỉ lr cho thấy chế độ để trở lại và bạn cần phải luôn luôn sử dụng bx trở

pre_thumb: 
ldr pc,lr 

thumb_capable: 
bx lr 

Trình biên dịch phân bổ một hướng dẫn bl để gọi chức năng, mối liên kết điền vào phần còn lại sau, nếu nó là quá xa tầm với sau đó nó cần một chức năng trampoline mà mối liên kết được thêm chính nó. Tương tự như vậy nếu bạn cần thay đổi các chế độ, bl gọi hàm trampoline để thực hiện điều đó. Tôi đã mô hình hóa một trong những điều trên để bắt chước, bạn có thể thấy nó hơi lãng phí, hy vọng lời giải thích của tôi về trình biên dịch chỉ phân bổ không gian cho một bl làm cho rõ ràng hơn, lãng phí sẽ luôn luôn có kế hoạch thay đổi chế độ và phải chèn nops cho phần lớn các cuộc gọi hàm trong mã.

Mã này cũng bao gồm một cuộc gọi đến cánh tay từ ngón tay cái trong lắp ráp:

.thumb 

.thumb_func 
.globl XPUT32 
XPUT32: 
    push {lr} 
    ;@ call an arm function from thumb asm 
    ldr r2,=PUT32 
    mov lr,pc 
    bx r2 
    pop {r2} 
    bx r2 

chủ yếu là giống nhau ngoại trừ bạn không thể bật để LR trong chế độ ngón tay cái, bạn có thể bật để pc, nhưng tôi không nghĩ rằng đó chuyển chế độ , vì vậy bạn không thể sử dụng nó, bạn lại cần một thanh ghi phụ tùng. Bạn tất nhiên cần phải biết các công ước gọi để biết những gì đăng ký bạn có thể sử dụng hoặc bạn có thể quấn một bộ push và bật để bảo vệ tất cả nhưng lr

push {r2,lr} 
    ;@ call an arm function from thumb asm 
    ldr r2,=PUT32 
    mov lr,pc 
    bx r2 
    pop {r2} 
    mov lr,r2 
    pop {r2} 
    bx lr 

Thumb để ngón tay cái hoặc cánh tay để cánh tay bạn chỉ cần sử dụng một bl nếu bạn có thể đạt được. ldr pc, địa chỉ nếu bạn không thể.

0

Nếu bạn tập hợp mã asm thành Thumb, bạn cần đánh dấu hàm là hàm Thumb, để trình liên kết sử dụng lệnh đúng khi phân nhánh tới nó (ví dụ: BLX hoặc BX đến địa chỉ có bộ bit thấp). Điều này được thực hiện với.thumb_func chỉ:

.global activate 
.thumb_func 
activate: 
    b test 

Một lựa chọn khác là yêu cầu một cách rõ ràng lắp ráp để tạo ra mã ARM:

.code 32 
.global activate 
activate: 
    b test 

Kiểm tra this article quá, mặc dù nhớ rằng bộ vi xử lý hiện tại không cần nhiều cách giải quyết đó là cần thiết trong ARMv4 , vì vậy bạn có lẽ không nên theo dõi nó một cách mù quáng.

0

Để loại bỏ sự nhầm lẫn:

Vấn đề là trình biên dịch chéo GCC của Ubuntu cho ARM tạo ra hướng dẫn ngón tay cái (16 bit) theo mặc định. Như các câu trả lời khác ở đây cho thấy, gọi giữa hai là có thể, nhưng trong khi bộ phối hợp GNU phát hiện ra rằng mã C đã tạo ra các chỉ dẫn ngón tay cái và do đó tạo ra shims vui vẻ bằng bx để đặt chế độ chính xác để gọi thành C, tôi không kiểm soát được trên những gì GCC tự tạo ra cho các chức năng gọi điện, và nó đã gọi chúng với chỉ bl, mà đã phá vỡ vì mã assembly của tôi cần phải là các lệnh ARM (32-bit).

Giải pháp (vốn kém tài liệu) là gửi gcc -marm, ít nhất sẽ làm cho tất cả mã cùng loại.

Nếu có chuyển đổi để nhận gcc để tạo các cuộc gọi bx cho các chức năng, điều đó có thể cũng sẽ hoạt động.

+0

gcc -marm không hoạt động đối với tôi. Tôi cần mã lắp ráp cho arm-v4t-linux-gnueabi –

Các vấn đề liên quan