As an example I m trying to see how division is implemented on arm and arm64.
created a test.c
int main(void)
{
int a = 10;
int b = 20;
return (a/b);
}
Make sure to comple with -o option always because a.out doesn't has symbols
To compile for arm64
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gccc -o test64 test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm64/usr/
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004005a8 <+0>: sub sp, sp, #0x10
0x00000000004005ac <+4>: mov w0, #0xa // #10
0x00000000004005b0 <+8>: str w0, [sp,#12]
0x00000000004005b4 <+12>: mov w0, #0x14 // #20
0x00000000004005b8 <+16>: str w0, [sp,#8]
0x00000000004005bc <+20>: ldr w1, [sp,#12]
0x00000000004005c0 <+24>: ldr w0, [sp,#8]
0x00000000004005c4 <+28>: sdiv w0, w1, w0
0x00000000004005c8 <+32>: add sp, sp, #0x10
0x00000000004005cc <+36>: ret
End of assembler dump.
start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc -o test test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm/usr/
To compile for arm
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test
start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test
Dump of assembler code for function main:
0x00008460 <+0>: push {r11, lr}
0x00008464 <+4>: add r11, sp, #4
0x00008468 <+8>: sub sp, sp, #8
0x0000846c <+12>: mov r3, #10
0x00008470 <+16>: str r3, [r11, #-8]
0x00008474 <+20>: mov r3, #20
0x00008478 <+24>: str r3, [r11, #-12]
0x0000847c <+28>: ldr r0, [r11, #-8]
0x00008480 <+32>: ldr r1, [r11, #-12]
0x00008484 <+36>: bl 0x8498 <__divsi3>
0x00008488 <+40>: mov r3, r0
0x0000848c <+44>: mov r0, r3
0x00008490 <+48>: sub sp, r11, #4
0x00008494 <+52>: pop {r11, pc}
End of assembler dump.
So arm32 implements division in software whereas arm64 has a dedicated instruction to do this.
created a test.c
int main(void)
{
int a = 10;
int b = 20;
return (a/b);
}
Make sure to comple with -o option always because a.out doesn't has symbols
To compile for arm64
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gccc -o test64 test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm64/usr/
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004005a8 <+0>: sub sp, sp, #0x10
0x00000000004005ac <+4>: mov w0, #0xa // #10
0x00000000004005b0 <+8>: str w0, [sp,#12]
0x00000000004005b4 <+12>: mov w0, #0x14 // #20
0x00000000004005b8 <+16>: str w0, [sp,#8]
0x00000000004005bc <+20>: ldr w1, [sp,#12]
0x00000000004005c0 <+24>: ldr w0, [sp,#8]
0x00000000004005c4 <+28>: sdiv w0, w1, w0
0x00000000004005c8 <+32>: add sp, sp, #0x10
0x00000000004005cc <+36>: ret
End of assembler dump.
start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc -o test test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm/usr/
To compile for arm
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test
start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test
Dump of assembler code for function main:
0x00008460 <+0>: push {r11, lr}
0x00008464 <+4>: add r11, sp, #4
0x00008468 <+8>: sub sp, sp, #8
0x0000846c <+12>: mov r3, #10
0x00008470 <+16>: str r3, [r11, #-8]
0x00008474 <+20>: mov r3, #20
0x00008478 <+24>: str r3, [r11, #-12]
0x0000847c <+28>: ldr r0, [r11, #-8]
0x00008480 <+32>: ldr r1, [r11, #-12]
0x00008484 <+36>: bl 0x8498 <__divsi3>
0x00008488 <+40>: mov r3, r0
0x0000848c <+44>: mov r0, r3
0x00008490 <+48>: sub sp, r11, #4
0x00008494 <+52>: pop {r11, pc}
End of assembler dump.
So arm32 implements division in software whereas arm64 has a dedicated instruction to do this.
2 comments:
Nice post Arun.
One query, is it absolutely require to have knowledge of "arm instructions set" FULLY
in order to solve kernel oops?
IMO it is very difficult to learn arm instruction set fully. You can always refer the manual. Why to store everything unnecessarily in your memory. :-)
Post a Comment