简体   繁体   中英

C to arm assembly code conversion

I have written a program in c and converted it to arm assembly, now I am having problem in understanding some instruction generated in the assembly code. A part of C program is:

#define MAX_DIGIT 1024
int main()
{
    int fd[MAX_DIGIT];
    int xLen = 0;
    int sd[MAX_DIGIT];
    int yLen = 0;

    int result[6*MAX_DIGIT];

    // Take input for two numbers
    takeInput(fd, &xLen);
    takeInput(sd, &yLen);   
        ...
        ...
        ...
}
...
...
...

void takeInput(int digit[], int *length)
{
    char c;
    if((c=getchar()) != '\n' && *length <= MAX_DIGIT){
        takeInput(digit, length);
        digit[*length] = c - '0';
        (*length)++;
    }else return;
}

I have converted this c code to arm assembly code using gnu arm toolchain. And a part of generated assembly code is:

main:
    @ args = 0, pretend = 0, frame = 32788
    @ frame_needed = 1, uses_anonymous_args = 0
    mov ip, sp
    stmfd   sp!, {fp, ip, lr, pc}
    sub fp, ip, #4
    sub sp, sp, #32768
    sub sp, sp, #20       @Why subtracted 20? 

    mvn r3, #4096
    sub r3, r3, #3
          @What r3 storing and Why took NOT of r3 and again subtract 3 from it?
    mov r2, #0
    sub r0, fp, #12
    str r2, [r0, r3]
    mvn r3, #8192
    sub r3, r3, #7
    mov r2, #0
    sub r1, fp, #12
    str r2, [r1, r3]
    sub r2, fp, #4096
    sub r2, r2, #12
    sub r3, fp, #4096
    sub r3, r3, #12
    sub r3, r3, #4
    mov r0, r2
    mov r1, r3
    bl  takeInput
    sub r2, fp, #8192
    sub r2, r2, #12
    sub r2, r2, #4
    sub r3, fp, #8192
    sub r3, r3, #12
    sub r3, r3, #8
    mov r0, r2
    mov r1, r3
    bl  takeInput
    mvn r3, #32768
    sub r3, r3, #11
    mov r2, #1
    sub ip, fp, #12
    str r2, [ip, r3]

I have marked my dought in the assembly code itself in the comments. Thanks.

The immediate numbers (constants that are encoded in parts of instructions) can have only certain values because the fields that encode them have only a few bits. When the compiler wants to load a register with a value that can not be encoded with an immediate value, it loads part of the value and then uses arithmetic to finish it.

There are different encodings of immediate values in different ARM instructions, but here is one as an example from the ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition. The “modified immediate constants in ARM instructions” are encoded as 12 bits. Four bits specify a rotation, and eight bits are literal bits for the value. The four bits form a binary numeral, and the rotation amount is twice that numeral, to the right. Eg, if the four bits are 0011, which is three, then the rotation amount is six bits.

So, if the four rotation bits are 0011, and the eight literal bits are 10011101, then the value is formed by rotating 10011101 six bits right within a 32-bit field. So 0000 0000 0000 0000 0000 0000 1001 1101 is rotated right six bits, producing 0110 0100 0000 0000 0000 0000 0000 0010, or 0x64000002.

Obviously, 12 bits cannot encode all possible 32-bit values. One of the values the compiler wants in your example is 32748, which is 0x7fec. We cannot form 0x7fec from just eight bits in any position (or, more specifically, an even-indexed position).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM