当前位置:网站首页>Arm V7 continuous load / store

Arm V7 continuous load / store

2022-06-25 12:12:00 xiaozhiwise

/*
 * 2018/12/18    10:15    qing
 */


/*
 * Continuous loading / Storage
 */

     Use LDM(load multiple) as well as STM(store multiple)


    stmdb r0!, {r4-r11, r14}    /* Register R4~R11 Also save to stack r0 in     [[ From register to memory ]] */
    ldmia r0!, {r4-r11, r14}    /* From the stack r0 Back to R4~R11,R14            [ [ From memory to register ]] */


    
    .data

    array_buff:
        .word    0x00000000    /* array_buff[0] */
        .word    0x00000000    /* array_buff[1] */
        .word    0x00000000    /* array_buff[2] This item points to array_buff+8 The pointer to */
        .word    0x00000000    /* array_buff[3] */
        .word    0x00000000    /* array_buff[4] */

    .text
    .global main

    main:
        adr r0, words + 12                /* wrods[3] The address of   ---> r0 */
        ldr r1, array_buff_bridge        /* array_buff[0] The address of -> r1 */
        ldr r2, array_buff_bridge + 4    /* array_buff[2] The address of -> r2 */
        ldm r0, {r4, r5}                /* words[3] --> r4 = 0x03; words[4] --> r5 = 0x04 */
        stm r1, {r4, r5}                /* r4 --> array_buff[0] = 0x03; r5 --> array_buff[1] = 0x04 */

        ldmia r0, {r4-r6}                /* words[3] --> r4 = 0x03, words[4] --> r5 = 0x04; words[5] --> r6 = 0x05 */
        stmia r1, {r4-r6}                /* r4 --> array_buff[0] = 0x03; r5 --> array_buff[1] = 0x4; r6 --> array_buff[2] = 0x5 */
        
        ldmib r0, {r4-r6}                /* words[4] --> r4 = 0x04; words[5] --> r5 = 0x05; words[6] --> r6 = 0x06 */
        stmib r1, {r4-r6}                /* r4 --> array_buff[1] = 0x04; r5 --> array_buff[2] = 0x05; r6 --> array_buff[3] = 0x06 */
        
        ldmda r0, {r4-r6}                /* words[3] --> r6 = 0x03; words[2] --> r5 = 0x02; words[1] --> r4 = 0x01 */
        ldmdb r0, {r4-r6}                /* words[2] --> r6 = 0x02; words[1] --> r5 = 0x01; words[0] --> r4 = 0x00 */
        
        stmda r2, {r4-r6}                /* r6 --> array_buff[2] = 0x02; r5 --> array_buff[1] = 0x01; r4 --> array_buff[0] = 0x00 */
        stmdb r2, {r4-r6}                /* r5 --> array_buff[1] = 0x01; r4 --> array_buff[0] = 0x00 */
        
        bx lr

    .words:
        .word 0x00000000        /* words[0] */
        .word 0x00000001        /* words[1] */
        .word 0x00000002        /* words[2] */
        .word 0x00000003        /* words[3] */
        .word 0x00000004        /* words[4] */
        .word 0x00000005        /* words[5] */
        .word 0x00000006        /* words[6] */
    
    array_buff_bridge:
        .word    array_buff        /* array_buff[0] address */
        .word    array_buff + 8    /* array_buff[2] address */


    .word The identification is for the memory with a length of 32 Bit data block as a reference . This is important for understanding offsets in your code .
    
     So the program consists of .data Data composed of segments , A length of... Will be requested in the memory 5 Of 4 Byte array array_buff. All our memory storage operations , All are read and write to the data segment in the memory .
    
     and .text The end contains our code for memory operations and two read-only tags ,
    
     A tag is an array of seven elements , The other is to link .text Paragraph and .data The existence of a segment is for array_buff References to .


/*
 * Let's start line by line analysis
 */

    adr r0, words+12             /* words[3] The address of -> r0 */

         use ADR Command to get words[3] The address of , Coexist to R0 in . We chose a middle position because we have to do forward and backward operations later .

        gef> break _start
        gef> run
        gef> nexti
        
        R0 There is now words[3] The address of the , That is to say 0x80B8. in other words , Our array word[0] The address is :0x80AC(0x80B8-0XC).

        gef> x/7w 0x00080AC
        0x80ac <words>: 0x00000000 0x00000001 0x00000002 0x00000003        /* 0x80ac 80B0 80B4 80B8 */
        0x80bc <words+16>: 0x00000004 0x00000005 0x00000006                /* 0x80bc 80C0 80C4         */

         Next, we will R1 and R2 Point to array_buff[0] as well as array_buff[2]. After getting these pointers , We can manipulate this array .


    ldr r1, array_buff_bridge    /* array_buff[0] The address of -> r1 */
    ldr r2, array_buff_bridge+4  /* array_buff[2] The address of -> r2 */

         After executing the above two instructions ,R1 and R2 The change of .
        gef> info register r1 r2
        r1      0x100d0     65744        /* 0x100d0 = 65744 */
        r2      0x100d8     65752        /* 0x100d8 = 65752 */

         The next one LDM Command from R0 Two words of data are loaded in the memory pointed to . because R0 Point to words[3] At the beginning of , therefore words[3] The value is assigned to R4,words[4] The value is assigned to R5.

    ldm r0, {r4,r5}              /* words[3] -> r4 = 0x03; words[4] -> r5 = 0x04 */

         So we load two data blocks with one instruction , And put it in R4 and R5 in .

        gef> info registers r4 r5
        r4      0x3      3
        r5      0x4      4


    
        STM Instructions will be R4 And R5 The value in 0x3 and 0x4 Store in R1 Point to memory . here R1 Pointing to array_buff[0], in other words array_buff[0] = 0x00000003
        
         as well as array_buff[1] = 0x00000004 . If not specified ,LDM And STM The smallest unit of instruction operation is a word ( Four bytes ).

    stm r1, {r4,r5}              /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04 */
    
         value 0x3 And 0x4 It's stored in R1 Where to point 0x100D0 as well as 0x100D4.

        gef> x/2w 0x000100D0
        0x100d0 <array_buff>:  0x00000003   0x00000004

    

         I said before LDM and STM There are many forms . Different forms of extended characters have different meanings :

        IA(increase after)
        IB(increase before)
        DA(decrease after)
        DB(decrease before)

         The main basis for these extensions is , The pointer to the source address or destination address is increased or decreased before accessing memory , Or increase or decrease after accessing memory . as well as ,LDM And LDMIA Function the same ,
        
         The address is added after the loading operation is completed . In this way , We can serially load data from the memory pointed to by a pointer to the register forward or backward ,
        
         Or store data in memory . The following schematic code .

    ldmia r0, {r4-r6}    /* words[3] -> r4 = 0x03, words[4] -> r5 = 0x04; words[5] -> r6 = 0x05; */
    stmia r1, {r4-r6}    /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04; r6 -> array_buff[2] = 0x05 */

         After executing these two codes ,R4 To R6 The memory address and value accessed by the register are   0x000100D0 , 0x000100D4 , as well as 0x000100D8 , The value corresponds to 0x3,0x4, as well as 0x5 .

        gef> info registers r4 r5 r6
        r4     0x3     3
        r5     0x4     4
        r6     0x5     5
        gef> x/3w 0x000100D0
        0x100d0 <array_buff>: 0x00000003  0x00000004  0x00000005

         and LDMIB The instruction will first add... To the address pointed to 4 , Then load the data into the register . So the pointer will also be added when loading for the first time 4 ,
        
         So what is stored in the register is 0x4 (words[4]) instead of 0x3 (words[3])

    dmib r0, {r4-r6}            /* words[4] -> r4 = 0x04; words[5] -> r5 = 0x05; words[6] -> r6 = 0x06 */
    stmib r1,{r4-r6}            /* r4 -> array_buff[1] = 0x04; r5 -> array_buff[2] = 0x05; r6 -> array_buff[3] = 0x06 */

         After execution
        gef> x/3w 0x100D4
        0x100d4 <array_buff+4>: 0x00000004  0x00000005  0x00000006
        gef> info register r4 r5 r6
        r4     0x4    4
        r5     0x5    5
        r6     0x6    6

         When used LDMDA When the command , The reverse operation is performed .R0 Point to words[3], When loading data, the loading direction of the data changes to loading words[3],words[2],words[1] Value to R6,R5,R4 in .
        
         The reason for this loading process is that we LDM The suffix of the instruction is DA, That is, after the loading operation is completed , Will decrement the pointer . Note that the register operation in subtraction mode is reversed ,
        
         The reason for this setting is to maintain the principle of allowing large numbered registers to access high address memory .

         Load more than once , Post subtraction :

    ldmda r0, {r4-r6} /* words[3] -> r6 = 0x03; words[2] -> r5 = 0x02; words[1] -> r4 = 0x01 */

         After performing ,R4-R6 Value :
        gef> info register r4 r5 r6
        r4     0x1    1
        r5     0x2    2
        r6     0x3    3

         Load more than once , Pre subtraction :

    ldmdb r0, {r4-r6} /* words[2] -> r6 = 0x02; words[1] -> r5 = 0x01; words[0] -> r4 = 0x00 */

         After performing ,R4-R6 Value :
        gef> info register r4 r5 r6
        r4 0x0 0
        r5 0x1 1
        r6 0x2 2

         Multiple storage , Post subtraction :

    stmda r2, {r4-r6} /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */

         After performing ,array_buff[2],array_buff[1], as well as array_buff[0] Value :
        gef> x/3w 0x100D0
        0x100d0 <array_buff>: 0x00000000 0x00000001 0x00000002

         Multiple storage , Pre subtraction :

    stmdb r2, {r4-r5} /* r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00; */

         After performing ,array_buff[1], as well as array_buff[0] Value :
        gef> x/2w 0x100D0
        0x100d0 <array_buff>: 0x00000000 0x00000001

原网站

版权声明
本文为[xiaozhiwise]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/176/202206251202417173.html