2012-02-20 28 views
13

Tôi đang cố gắng tìm hiểu các kỹ năng hữu ích trong việc sửa đổi phần mềm (mà tôi không có mã nguồn) Những câu hỏi này liên quan đến việc sử dụng BX từ mã ngón tay cái để nhảy hoặc gọi mã ngón tay cái hiện có khác.Cánh tay/ngón tay cái: sử dụng BX trong mã Thumb, để gọi hàm Thumb hoặc để chuyển sang hướng dẫn Thumb trong một chức năng khác

  1. Làm cách nào để sử dụng BX đến JUMP cho mã phần mềm THUMB hiện tại, từ mã THUMB của tôi.
  2. Làm cách nào để sử dụng BX để GỌI một hàm THUMB hiện có (phải đặt LR trước), từ mã THUMB của tôi.

Sự hiểu biết của tôi là CPU xem bit lsb (bit 0) và tôi phải đảm bảo điều này được đặt thành 1 để giữ trạng thái CPU ở trạng thái "ngón tay cái". Vì vậy, tôi đoán tôi phải ADD 1, để thiết lập LSB bit 1.

... Vì vậy, nói tôi muốn chỉ JUMP để 0x24000 (ở giữa một số mã THUMB hiện)

LDR R6, =0x24000 
ADD R6, #1  @ (set lsb to 1) 
BX R6 

Tôi nghĩ rằng điều này là đúng ?

Bây giờ nói tôi muốn CALL một chức năng ngón tay cái hiện có, sử dụng BX, và tôi muốn nó trở lại với tôi, vì vậy tôi cần phải đặt LR đến nơi tôi muốn nó trở lại.

phép nói rằng chức năng tôi muốn gọi là 0x24000 Đó là suggested to me sử dụng:

ldr r2, =0x24000 
mov lr, pc 
bx r2 

Ở đây có những gì tôi không hiểu:

  1. địa chỉ trong R2 doesn không có bộ bit lsb ... vì vậy sẽ không bx r2 chế độ chuyển sang chế độ ARM?

  2. LR .. PC có địa chỉ (bắt đầu hướng dẫn hiện tại, + 4), tôi được thông báo. Trong cả hai ngón tay cái và cánh tay, bất kỳ địa chỉ hướng dẫn nào phải được căn chỉnh (16 bit hoặc 32 bit), vì vậy nó sẽ không có bit LSB được đặt thành 1. Chỉ số lẻ có bit lsb được đặt thành 1.

Vì vậy, trong đoạn mã trên, tôi đang đặt LR thành (PC), một địa chỉ KHÔNG CÓ bộ bit lsb 1. Vì vậy, khi hàm tôi gọi là phần kết của nó, và BX LR, ... uhmmm .. làm sao nó có thể hoạt động để trở về mã THUMB của tôi? Tôi phải thiếu một cái gì đó ...

Thông thường BL được sử dụng để gọi hàm. Hướng dẫn này cho biết lệnh BL đặt LR thành dòng mã tiếp theo ... Vậy điều này có nghĩa là hướng dẫn THUẾ (thường được sử dụng) BL THUMB, tự động đặt LR thành return addr + 1?

Trả lời

19

Wow, cảm ơn vì đã gọi cho tôi về điều này. Tôi biết tôi đã thử mã qemu trong http://github.com/dwelch67/yagbat và nghĩ XPUT32 gọi PUT32 theo cách bạn mô tả và nó hoạt động. Nhưng nó KHÔNG xuất hiện để làm việc. Tôi đã tạo ra một số thí nghiệm và khá ngạc nhiên, đây không phải là những gì tôi mong đợi. Bây giờ tôi thấy lý do tại sao gnu linker làm những gì nó làm. Xin lỗi đây là một phản hồi dài nhưng tôi nghĩ nó rất có giá trị. Nó là một chủ đề khó hiểu, tôi biết tôi đã có nó sai trong nhiều năm suy nghĩ pc kéo chế độ bit xung quanh, nhưng nó không.

Trước khi tôi bắt đầu với các thí nghiệm dưới đây, nếu bạn đang đi để làm điều này:

LDR R6, =0x24000 
ADD R6, #1  @ (set lsb to 1) 
BX R6 

vì bạn tình cờ biết rằng 0x24000 là mã ngón tay cái, chỉ cần làm điều này thay vì:

LDR R6, =0x24001 
BX R6 

Và có, đó là cách bạn chi nhánh để ngón tay cái mã từ cánh tay hoặc ngón tay cái nếu bạn xảy ra để biết rằng địa chỉ hardcoded 0x24000 là một ngón tay cái hướng dẫn bạn bx với một đăng ký có chứa địa chỉ cộng với một.

nếu bạn không biết địa chỉ nhưng biết tên của địa chỉ

ldr r6,=something 
bx r6 

Những điều tốt đẹp về điều đó là một cái gì đó có thể là một cánh tay hoặc ngón tay cái địa chỉ và mã số trên chỉ hoạt động. Vâng nó hoạt động nếu mối liên kết đúng cách biết những gì loại nhãn đó là cánh tay hoặc ngón tay cái, nếu điều đó được điều sai lầm đó sẽ không làm việc đúng như bạn có thể thấy ở đây

.thumb 
ping: 
    ldr r0,=pong 
    bx r0 
.code 32 
pong: 
    ldr r0,=ping 
    bx r0 


d6008148 <ping>: 
d6008148: 4803  ldr r0, [pc, #12] ; (d6008158 <pong+0xc>) 
d600814a: 4700  bx r0 

d600814c <pong>: 
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10> 
d6008150: e12fff10 bx r0 

d6008158: d600814c strle r8, [r0], -ip, asr #2 
d600815c: d6008148 strle r8, [r0], -r8, asr #2 

rằng didnt pong việc muốn kéo một địa chỉ ngón tay cái từ 0xD600815C nhưng có địa chỉ cánh tay.

đây là tất cả các công cụ lắp ráp gnu btw, cho các công cụ khác bạn có thể phải làm điều gì đó khác. Đối với khí bạn cần phải đặt .thumb_func trước nhãn mà bạn muốn khai báo dưới dạng nhãn ngón tay cái (thuật ngữ hàm func ngụ ý là gây hiểu nhầm, đừng lo lắng về điều gì .thumb_func có nghĩa là nó chỉ là một trò chơi lắp ráp/liên kết).

.thumb 
.thumb_func 
ping: 
    ldr r0,=pong 
    bx r0 
.code 32 
pong: 
    ldr r0,=ping 
    bx r0 

và bây giờ chúng ta có được những gì chúng tôi muốn

d6008148 <ping>: 
d6008148: 4803  ldr r0, [pc, #12] ; (d6008158 <pong+0xc>) 
d600814a: 4700  bx r0 

d600814c <pong>: 
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10> 
d6008150: e12fff10 bx r0 

d6008158: d600814c strle r8, [r0], -ip, asr #2 
d600815c: d6008149 strle r8, [r0], -r9, asr #2 

0xD600815C đã lsbit rằng thiết để bạn không cần phải làm bất cứ công việc. Trình biên dịch sẽ xử lý tất cả điều này khi bạn đang thực hiện các cuộc gọi đến các hàm C chẳng hạn. Đối với assembler mặc dù bạn phải sử dụng nó .thumb_func (hoặc một số chỉ thị khác nếu có một) để có được khí để biết đây là một nhãn ngón tay cái và thiết lập các lsbit cho bạn.

Vì vậy, thử nghiệm dưới đây được thực hiện trên một mpcore là ARM11 nhưng tôi cũng đã thử các chức năng testthumb từ 1 đến 4 trên ARM7TDMI và qemu với cùng kết quả.

.globl testarm 
testarm: 
    mov r0,pc 
    bx lr 

armbounce: 
    mov r0,lr 
    bx lr 

.thumb 
.thumb_func 
.globl testthumb1 
testthumb1: 
    mov r0,pc 
    bx lr 
    nop 
    nop 
    nop 
bounce: 
    bx lr 
.thumb_func 
.globl testthumb2 
testthumb2: 
    mov r2,lr 
    mov r0,pc 
    bl bounce 
    bx r2 
    nop 
    nop 
    nop 
.thumb_func 
.globl testthumb3 
testthumb3: 
    mov r2,lr 
    mov lr,pc 
    mov r0,lr 
    bx r2 
    nop 
    nop 
    nop 
.thumb_func 
.globl testthumb4 
testthumb4: 
    push {lr} 
    ldr r2,=armbounce 
    mov r1,pc ;@ -4 
    add r1,#5 ;@ -2 
    mov lr,r1 ;@ +0 
    bx r2  ;@ +2 
    pop {r2} ;@ +4 
    bx r2 
.thumb_func 
.globl testthumb5 
testthumb5: 
    push {lr} 
    ldr r2,=armbounce 
    mov lr,pc 
    bx r2 
    pop {r2} 
    bx r2 
.thumb_func 
.globl testthumb6 
testthumb6: 
    push {lr} 
    bl testthumb6a 
.thumb_func 
testthumb6a: 
    mov r0,lr 
    pop {r2} 
    bx r2 

.thumb_func 
.globl testthumb7 
testthumb7: 
    push {lr} 
    bl armbounce_thumb 
    pop {r2} 
    bx r2 

.thumb_func 
.globl testthumb8 
testthumb8: 
    push {lr} 
    bl armbounce_thumb_two 
    pop {r2} 
    bx r2 

.align 4 
armbounce_thumb: 
    ldr r1,[pc] 
    bx r1 
.word armbounce 

nop 
.align 4 
armbounce_thumb_two: 
    bx pc 
    nop 
.code 32 
    b armbounce 

mà trở nên

d60080b4 <testarm>: 
d60080b4: e1a0000f mov r0, pc 
d60080b8: e12fff1e bx lr 

d60080bc <armbounce>: 
d60080bc: e1a0000e mov r0, lr 
d60080c0: e12fff1e bx lr 

d60080c4 <testthumb1>: 
d60080c4: 4678  mov r0, pc 
d60080c6: 4770  bx lr 
d60080c8: 46c0  nop   ; (mov r8, r8) 
d60080ca: 46c0  nop   ; (mov r8, r8) 
d60080cc: 46c0  nop   ; (mov r8, r8) 

d60080ce <bounce>: 
d60080ce: 4770  bx lr 

d60080d0 <testthumb2>: 
d60080d0: 4672  mov r2, lr 
d60080d2: 4678  mov r0, pc 
d60080d4: f7ff fffb bl d60080ce <bounce> 
d60080d8: 4710  bx r2 
d60080da: 46c0  nop   ; (mov r8, r8) 
d60080dc: 46c0  nop   ; (mov r8, r8) 
d60080de: 46c0  nop   ; (mov r8, r8) 

d60080e0 <testthumb3>: 
d60080e0: 4672  mov r2, lr 
d60080e2: 46fe  mov lr, pc 
d60080e4: 4670  mov r0, lr 
d60080e6: 4710  bx r2 
d60080e8: 46c0  nop   ; (mov r8, r8) 
d60080ea: 46c0  nop   ; (mov r8, r8) 
d60080ec: 46c0  nop   ; (mov r8, r8) 

d60080ee <testthumb4>: 
d60080ee: b500  push {lr} 
d60080f0: 4a15  ldr r2, [pc, #84] ; (d6008148 <armbounce_thumb_two+0x8>) 
d60080f2: 4679  mov r1, pc 
d60080f4: 3105  adds r1, #5 
d60080f6: 468e  mov lr, r1 
d60080f8: 4710  bx r2 
d60080fa: bc04  pop {r2} 
d60080fc: 4710  bx r2 

d60080fe <testthumb5>: 
d60080fe: b500  push {lr} 
d6008100: 4a11  ldr r2, [pc, #68] ; (d6008148 <armbounce_thumb_two+0x8>) 
d6008102: 46fe  mov lr, pc 
d6008104: 4710  bx r2 
d6008106: bc04  pop {r2} 
d6008108: 4710  bx r2 

d600810a <testthumb6>: 
d600810a: b500  push {lr} 
d600810c: f000 f800 bl d6008110 <testthumb6a> 

d6008110 <testthumb6a>: 
d6008110: 4670  mov r0, lr 
d6008112: bc04  pop {r2} 
d6008114: 4710  bx r2 

d6008116 <testthumb7>: 
d6008116: b500  push {lr} 
d6008118: f000 f80a bl d6008130 <armbounce_thumb> 
d600811c: bc04  pop {r2} 
d600811e: 4710  bx r2 

d6008120 <testthumb8>: 
d6008120: b500  push {lr} 
d6008122: f000 f80d bl d6008140 <armbounce_thumb_two> 
d6008126: bc04  pop {r2} 
d6008128: 4710  bx r2 
d600812a: 46c0  nop   ; (mov r8, r8) 
d600812c: 46c0  nop   ; (mov r8, r8) 
d600812e: 46c0  nop   ; (mov r8, r8) 

d6008130 <armbounce_thumb>: 
d6008130: 4900  ldr r1, [pc, #0] ; (d6008134 <armbounce_thumb+0x4>) 
d6008132: 4708  bx r1 
d6008134: d60080bc   ; <UNDEFINED> instruction: 0xd60080bc 
d6008138: 46c0  nop   ; (mov r8, r8) 
d600813a: 46c0  nop   ; (mov r8, r8) 
d600813c: 46c0  nop   ; (mov r8, r8) 
d600813e: 46c0  nop   ; (mov r8, r8) 

d6008140 <armbounce_thumb_two>: 
d6008140: 4778  bx pc 
d6008142: 46c0  nop   ; (mov r8, r8) 
d6008144: eaffffdc b d60080bc <armbounce> 
d6008148: d60080bc   ; <UNDEFINED> instruction: 0xd60080bc 
d600814c: e1a00000 nop   ; (mov r0, r0) 

Và kết quả của việc gọi và in tất cả các chức năng

D60080BC testarm 
D60080C8 testthumb1 
D60080D6 testthumb2 
D60080E6 testthumb3 
D60080FB testthumb4 
     testthumb5 crashes 
D6008111 testthumb6 
D600811D testthumb7 
D6008127 testthumb8 

Vậy là những gì tất cả điều này làm và những gì nó phải làm với bạn câu hỏi. Điều này phải làm với chế độ hỗn hợp gọi từ chế độ ngón tay cái (và cũng từ cánh tay đơn giản hơn)

Tôi đã lập trình ARM và ngón tay cái ở cấp độ này trong nhiều năm và bằng cách nào đó. Tôi nghĩ rằng chương trình truy cập luôn luôn giữ chế độ trong đó lsbit, tôi biết như bạn biết rằng bạn muốn có nó thiết lập hoặc không được thiết lập khi bạn làm một lệnh bx.

Rất sớm trong mô tả CPU của bộ xử lý ARM trong Cẩm nang tham khảo kiến ​​trúc ARM (nếu bạn đang viết assembly, bạn đã có sẵn điều này, nếu không có thể hầu hết các câu hỏi của bạn sẽ được trả lời).

Program counter Register 15 is the Program Counter (PC). It can be used in most 
     instructions as a pointer to the instruction which is two instructions after 
     the instruction being executed... 

Vì vậy, hãy kiểm tra và xem điều đó thực sự có ý nghĩa gì, điều đó có nghĩa là trong chế độ cánh tay có hai hướng dẫn, 8 byte phía trước? và ở chế độ ngón tay cái, hai hướng dẫn phía trước hoặc 4 byte phía trước?

Vì vậy, kiểm thử xác minh rằng bộ đếm chương trình là 8 byte phía trước. đó cũng là hai hướng dẫn.

testthumb1 xác minh rằng chương trình là 4 byte phía trước, trong trường hợp này cũng là hai hướng dẫn.

testthumb2

d60080d2: 4678  mov r0, pc 
d60080d4: f7ff fffb bl d60080ce <bounce> 
d60080d8: 4710  bx r2 

nếu bộ đếm chương trình là hai "hướng dẫn" đầu chúng tôi sẽ nhận được 0xD60080D8 nhưng chúng tôi thay vì có được 0xD60080D6 mà là bốn byte phía trước, và có ý nghĩa hơn rất nhiều. Chế độ cánh tay 8 byte phía trước, chế độ ngón tay cái 4 byte phía trước, không gây rối với hướng dẫn giải mã (hoặc dữ liệu) phía trước mã đang được thực thi, chỉ cần thêm 4 hoặc 8.

testthumb3 là một hy vọng rằng mov lr, pc was đặc biệt, nó không phải.

nếu bạn chưa thấy mẫu, bộ lsbit của bộ đếm chương trình KHÔNG được đặt và tôi đoán điều này có ý nghĩa đối với bảng chi nhánh chẳng hạn. Vì vậy, mov lr, pc trong chế độ ngón tay cái KHÔNG thiết lập quyền đăng ký liên kết cho một sự trở lại.

testthumb4 theo một cách rất đau đớn không mất chương trình truy cập bất cứ nơi nào mã này xảy ra với cuối lên và dựa trên hướng dẫn đặt cẩn thận, tính toán địa chỉ trả lại, nếu bạn thay đổi điều đó chuỗi hướng dẫn giữa r1 mov, pc và bx r2 bạn phải trả lại phần bổ sung. Bây giờ, tại sao chúng ta không thể làm một cái gì đó như thế này:

add r1,pc,#1 
bx r2 

với ngón tay cái bạn có thể, với thumb2 bạn có thể có thể. Và dường như có một số bộ vi xử lý (armv7) hỗ trợ cả lệnh tay và thumb/thumb2, do đó bạn có thể đang ở trong tình huống mà bạn muốn thực hiện, nhưng bạn sẽ không thêm # 1 vì lệnh thumb2 add, nếu có cho phép các thanh ghi phía trên và có ba toán hạng sẽ là một lệnh 4 ngón tay cái 2 byte. (bạn sẽ cần phải thêm # 3).

Vì vậy, testthumb5 là trực tiếp từ mã tôi đã cho bạn thấy rằng dẫn đến một phần của câu hỏi này, và nó bị treo. đây không phải là cách nó hoạt động, xin lỗi tôi lừa dối folks Tôi sẽ cố gắng quay trở lại và vá lên các câu hỏi SO tôi sử dụng này với.

testthumb6 là một thử nghiệm để đảm bảo tất cả chúng ta đều không điên. Tất cả cũng là đăng ký liên kết thực sự có được bộ lsbit để khi bạn bx lr sau đó nó biết chế độ từ bit đó.

testthumb7, điều này có nguồn gốc từ trampoline bên ARM mà bạn thấy trình liên kết làm khi chuyển từ chế độ cánh tay sang chế độ ngón tay cái, trong trường hợp này mặc dù tôi đang chuyển từ chế độ ngón tay sang chế độ cánh tay. tại sao cant linker làm theo cách này? bởi vì trong chế độ ngón tay cái ít nhất bạn phải sử dụng một đăng ký thấp và vào thời điểm này trong trò chơi, sau khi mã được biên dịch các mối liên kết không có cách nào để biết những gì đăng ký nó có thể thùng rác. Trong chế độ cánh tay mặc dù đăng ký ip, không chắc chắn những gì có thể là r12, có thể nhận được thùng rác, tôi đoán nó được dành riêng cho trình biên dịch để sử dụng. Tôi biết trong trường hợp này r1 có thể nhận được thùng rác và sử dụng nó, và điều này hoạt động như mong muốn. mã armbounce được gọi là grabs đăng ký liên kết nếu nơi để quay trở lại, đó là một hướng dẫn ngón tay cái (bộ lsbit) sau khi bl armbounce_thumb trong hàm testthumb7, chính xác nơi chúng ta muốn nó được.

testthumb8 đây là cách trình liên kết gnu thực hiện khi cần chuyển từ chế độ ngón tay cái sang chế độ cánh tay. hướng dẫn bl được thiết lập để đi đến tấm bạt lò xo.sau đó họ làm điều gì đó rất rất phức tạp và điên rồ.

d6008140 <armbounce_thumb_two>: 
d6008140: 4778  bx pc 
d6008142: 46c0  nop   ; (mov r8, r8) 
d6008144: eaffffdc b d60080bc <armbounce> 

Máy tính bx. Chúng ta biết từ các thí nghiệm ở trên rằng máy tính là bốn byte phía trước, chúng ta cũng biết rằng các lsbit là KHÔNG SET. Vì vậy, điều này nói là chi nhánh cho MÃ ARM đó là bốn byte sau này. Nop là một bộ đệm hai byte, sau đó chúng ta phải tạo ra một lệnh ARM bốn byte phía trước VÀ BẬT TRÊN MỘT BỐN BTENG B ,NG B ,NG, và chúng ta tạo ra một nhánh vô điều kiện cho bất cứ nơi nào chúng ta đang đi, điều này có thể là một cái gì đó hoặc một máy tính ldr , = một cái gì đó tùy thuộc vào cách xa bạn cần phải đi. Rất khôn lanh.

Bản gốc bl arm_bounce_thumb_two thiết lập thanh ghi liên kết để trở về hướng dẫn sau đó bl. Tấm bạt lò xo không thay đổi thanh ghi liên kết nó chỉ thực hiện các nhánh.

nếu bạn muốn để có được chế độ ngón tay cái từ cánh tay sau đó làm những gì mối liên kết thực hiện:

... 
bl myfun_from_arm 
... 


myfun_from_arm: 
    ldr ip,[pc] 
    bx ip 
.word myfun 

mà trông như thế này khi họ làm điều đó (túm lấy từ một nhị phân khác nhau không phải ở 0xD6008xxx nhưng tại 0x0001xxxx).

101f8: eb00003a bl 102e8 <__testthumb1_from_arm> 


000102e8 <__testthumb1_from_arm>: 
    102e8: e59fc000 ldr ip, [pc] ; 102f0 <__testthumb1_from_arm+0x8> 
    102ec: e12fff1c bx ip 
    102f0: 00010147 andeq r0, r1, r7, asr #2 

vì vậy bất kỳ điều gì đăng ký ip này là (r12?), Chúng không phiền khi truy xuất và tôi cho rằng bạn được tự do chuyển vào thùng rác.

+0

hoàn toàn yêu câu trả lời của bạn và nỗ lực. Nó cũng là những gì tôi đã được chú ý trong firmware này dissasembled tôi đang làm việc trên. Và nó giải thích các sự cố trong thử nghiệm của tôi (không sử dụng trình giả lập .. chỉ cần cập nhật phần mềm điều chế và nạp chip flash ..lol) Phần vững có mã chế độ ARM, ở phần dưới và mã ngón tay cái chỉ dành cho phần ứng dụng chính . Nhưng có, đó là cách nó làm cho ngón tay cái và cánh tay để ngón tay cái. Phần mềm này được biên dịch với ADS v 1.2 btw. – vmanta

+0

Ngoài ra để thêm, như xa tôi có thể nói và như xa như tôi đã đọc, trong chế độ ngón tay cái (ngón tay cái 1 .. nếu theres một điều như vậy) bạn có thể thùng rác R0 - R3, nhưng bạn phải Push/Pop R4 - R7 . Phần vững tôi đang xem xét điều này, và tôi cũng nhận thấy mã từ gcc gnu (arm-elf-gcc) cũng vậy. Vâng .. nó là tuyệt vời bạn đã làm tất cả các bài kiểm tra, bởi vì tôi đã làm tương tự trên thiết bị trong mods phần vững của tôi, nhưng đôi khi tôi nhận được rất bối rối (đặc biệt là khi tai nạn xảy ra do những sai lầm khác) mà tôi resort để sử dụng BL (đau ở mông .... với tính toán bù đắp, như tôi đã giải thích) – vmanta

+0

Tôi sắp viết một chương trình được sử dụng như một bộ tiền xử lý để "làm" và thiết lập bù đắp cho tôi ... có thể sử dụng một số ký hiệu đặc biệt. .. như BL ADR: 0x24000, và prog của tôi để tính toán bù đắp này cho tôi ... ahhh .. đó sẽ là wonderfull .. tại sao không ai nghĩ rằng lol ... có lẽ có một cách mặc dù, tôi chỉ không biết nó được nêu ra .. và nếu có một cách tôi cho rằng nó sẽ là một số loại chỉ thị trong linker .. không biết nhưng tôi đọc và đọc .. đã dành quá nhiều thời gian. Hey cảm ơn rất nhiều người ... và vui vì bạn đã tìm được TRUTH .. hehe – vmanta

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