4

ARMアセンブリを学習しようとしていますが、コンピューターで生成された.sファイルに、主にこのブロックを混乱させる行がいくつかあります。

.L6:
   .word    .LC0-(.LPIC8+4)
   .word    .LC1-(.LPIC10+4
   .word    .LC0-(.LPIC11+4)

そしてそれがこのブロックにどのように関連しているか:

.LCFI0:
     ldr r3, .L6

.LPIC8:
     add r3, pc

私の推測では、これは私のASCII文字列(の先頭)のメモリアドレスをr3にロードしていると思いますが、これが正確にどのように行われているのか混乱しています。.LC0-(。LPIC8 + 4)は、add r3、pcが呼び出される場所と、文字列が配置される場所の違いです。その違いにpcを追加すると、文字列に戻るはずですが、直接呼び出すだけではどうでしょうか。

ldr r3, .LC0

これらの.wordのものと、この厄介なldr / addペアを持つ代わりに?これは、コンパイラがこれを処理するための唯一または最良の方法ですか、それともコンパイラがこのようなコードを生成するために使用する一般的なアルゴリズムの結果ですか?

また、何ですか

    @ sp needed for prologue

コンパイラがスタックポインタ処理をプロローグに追加することを思い出させるように聞こえます。しかし、私はそれがすでに起こっているはずであり、それはプロローグがどこにあるかではないように感じます。

以下は、私の正しいコメントを含むほとんどのアセンブリコードです(最後にいくつかのデバッグ機能がありますが、含めるには長すぎます。

誰もが提供できるどんな助けでも大歓迎です!

    .arch armv5te
    .fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 2
.eabi_attribute 18, 4
.code   16
.file   "helloneon.c"
.section    .debug_abbrev,"",%progbits
.Ldebug_abbrev0:
    .section    .debug_info,"",%progbits
.Ldebug_info0:
    .section    .debug_line,"",%progbits
.Ldebug_line0:
    .text
.Ltext0:
    .section    .text.main,"ax",%progbits
    .align  2
    .global main
    .code   16
    .thumb_func
    .type   main, %function
main:
    .fnstart
.LFB4:
    .file 1 "jni/helloneon.c"
    .loc 1 4 0
    .save   {r4, lr}
    push    {r4, lr}
.LCFI0:
    .loc 1 4 0
    ldr r3, .L6             ; r3 = char* hello, first position
.LPIC8:
    add r3, pc              ; pc = program counter, r3 += pc?
    .loc 1 3 0
    mov r1, r3              ; r1 = r3
    add r1, r1, #127        ; r1 += 127
.L2:
    .loc 1 10 0             ; r2 = holding an item in char* hello. r3 = pointer to location in hello
    ldrb    r2, [r3]        ; r2 = r3 load next char
    sub r2, r2, #32         ; r2 -=32 subtract 32 to char in register
    strb    r2, [r3]        ; r3 = r2 put uppercase char 
    add r3, r3, #1          ; r3 += 1
    .loc 1 8 0
    cmp r3, r1              ; compare r3, r1
    bne .L2                 ; if not equal, goto L2
    .loc 1 13 0
    ldr r0, .L6+4           ; r0 = 
    ldr r1, .L6+8           ; r1 = 
    .loc 1 16 0
    @ sp needed for prologue
    .loc 1 13 0
.LPIC10:
    add r0, pc              ; r0 += pc
.LPIC11:
    add r1, pc              ; r1 += pc
    bl  printf              ; goto printf
    .loc 1 16 0
    mov r0, #0              ; r0 = 0
    pop {r4, pc}            ; epilogue
.L7:
    .align  2
.L6:
    .word   .LC0-(.LPIC8+4)     ; 
    .word   .LC1-(.LPIC10+4)    ; 
    .word   .LC0-(.LPIC11+4)    ; 
.LFE4:
    .fnend
    .size   main, .-main
    .section    .rodata.str1.4,"aMS",%progbits,1
    .align  2
.LC0:
    .ascii  "helloworldthisismytestprogramtoconvertlowcharstobig"
    .ascii  "charsiamtestingneonandineedaninputofonehundredandtw"
    .ascii  "entyeightcharactersinleng\000"
.LC1:
    .ascii  "%s\000"
    .section    .debug_frame,"",%progbits
.Lframe0:
    .4byte  .LECIE0-.LSCIE0
.LSCIE0:
    .4byte  0xffffffff
    .byte   0x1
    .ascii  "\000"
    .uleb128 0x1
    .sleb128 -4
    .byte   0xe
    .byte   0xc
    .uleb128 0xd
    .uleb128 0x0
    .align  2

そしてここにcコードがあります:

#include <stdio.h>

int main()
{
    char* hello = "helloworldthisismytestprogramtoconvertlowcharstobigcharsiamtestingneonandineedaninputofonehundredandtwentyeightcharactersinleng"; // len = 127 + \0
    int i, size = 127;

    for (i = 0; i < size; i++)
    {
        hello[i] -= 32;
    }

    printf("%s", hello);

    return 0;
}
4

1 に答える 1

3

ldr r3, .L6疑似命令です。実際に変換されるのは、のようなものですldr r3,[pc, #offset]。ここoffsetで、LDR命令と、ロードしようとしている値の位置との間のメモリ内の距離です。ARMプロセッサの固定幅命令は、LDR / STR命令のオフセットに費やすビットが非常に多いことを意味します。つまり、PC相対ロードを介してロードされる値は、対応するロード命令のかなり近くに格納する必要があります。

.LC0はとは完全に異なるセクション.LPIC8にあるため、PC相対負荷の範囲外である可能性があります。

一部のARMアセンブラは、コードと同じセクション全体にリテラルの「プール」を分散させるために使用できる.LTORGディレクティブを提供します。たとえば、これは次のとおりです。

LDR r3,=.LC0   ; note the '='
....
.LTORG

このようなアセンブラでは、次のように変換されますか?

LDR r3,[pc,#offset_to_LC0Value]
....
LC0Value: .word .LC0


質問に示されているアセンブリコードでは、PCに相対的なのは負荷だけではありません。ロードされている値もPC相対です。その理由は、位置独立コードを取得するためです。絶対アドレスがロードされてから使用された場合、特定の仮想アドレスから実行されない限り、コードは失敗します。現在のPCに関連するアドレスを介してすべての関連データにアクセスすると、その依存関係を解消できます。

于 2012-12-18T21:09:57.273 に答える