簡體   English   中英

ARM程序集加載ASCII內存地址

[英]ARM assembly loading ASCII memory address

我正在嘗試學習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)是添加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;
}

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的地址訪問所有相關數據,可以打破這種依賴性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM