第12部分- Linux ARM汇编 控制指令
ARM的汇编控制如下:
- IF、ELSE及ENDIF
- WHILE及WEND
- MACRO及WEND
- MEXIT
32位示例
完成1+2+…+22。
.text.global mainmain: mov r1, #0 /* r1 ← 0 */ mov r2, #1 /* r2 ← 1 */loop: cmp r2, #22 /* compare r2 and 22 */ bgt end /* branch if r2 > 22 to end */ add r1, r1, r2 /* r1 ← r1 + r2 */ add r2, r2, #1 /* r2 ← r2 + 1 */ b loopend: mov r0, r1 /* r0 ← r1 */ bx lr复制代码
as -g -o loop01.o loop01.s
gcc -o loop01 loop01.o
执行后通过echo $?获得结果为253。
修改代码中的#22为#100,就可以得到1+2+…+100=5050。
但是不能通过$?来获得结果,应为Linux中错误码的返回是8位的,5050超过8位了。
5050的二进制是1001110111010,后面八位是10111010,也就是186,改成#100后,通过echo $?返回的事186,但是通过gdb调试可以去查看r1其真实为5050。
64位示例
.arch armv8-a.global _start.text_start: mov x1, #0 /* r1 ← 0 */ mov x2, #1 /* r2 ← 1 */loop: cmp x2, #22 /* compare r2 and 22 */ bgt end /* branch if r2 > 22 to end */ add x1, x1, x2 /* r1 ← r1 + r2 */ add x2, x2, #1 /* r2 ← r2 + 1 */ b loopend: mov x0, x1 /* r0 ← r1 */ mov x8, 93svc 0复制代码
as -g -o loop64.o loop64.s
ld -o loop64 loop64.o
执行后如下:
echo $?
253
32示例冰雹猜想
Collatz猜想:即一个正整数x,如果是奇数就乘以3再加1,如果是偶数就析出偶数因数2ⁿ,这样经过若干个次数,最终回到1。
无论N是怎样一个数字,最终都回到谷底1。准确地说,是无法逃出落入底部的4-2-1循环。
.text.global mainmain: mov r1, #123 /* r1 ← 123 */ mov r2, #0 /* r2 ← 0 */loop: cmp r1, #1 /* compare r1 and 1 */ beq end /* branch to end if r1 == 1 */ and r3, r1, #1 /* r3 ← r1 & 1 */ cmp r3, #0 /* compare r3 and 0 */ bne odd /* branch to odd if r3 != 0 */even: mov r1, r1, ASR #1 /* r1 ← (r1 >> 1) */ b end_loopodd: add r1, r1, r1, LSL #1 /* r1 ← r1 + (r1 << 1) */ add r1, r1, #1 /* r1 ← r1 + 1 */ end_loop: add r2, r2, #1 /* r2 ← r2 + 1 */ b loop /* branch to loop */ end: mov r0, r2 bx lr复制代码
as -g -o collatz.o collatz.s
gcc -o collatz collatz.o
执行后如下:
./collatz
echo $?
46
表示经过了46次变化。
入参为123,经过的步骤为:
[123, 370, 185, 556, 278, 139, 418, 209, 628, 314, 157, 472, 236, 118, 59, 178, 89, 268, 134, 67, 202, 101, 304, 152, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
C代码
#include <stdio.h>#include <stdint.h>int main (){ unsigned long long i,n,x = 0; //i是不断变高的数 int count = 0; int max = 0; n = 123; i = n; while(i!=1) { if(i %2 == 1) //如果是个奇数 { i=3*i+1; } else if(i %2 == 0) //如果是个偶数 { i=i/2; } count++; //累加转换次数 } printf("当前:%llu[变换次数%d]\n",n, count); return 0;}复制代码
gcc -o collatz-c collatz.c
结果也是46次变化。
64位示例冰雹猜想
.arch armv8-a.global _start.text_start: mov x1, #123 /* r1 ← 123 */ mov x2, #0 /* r2 ← 0 */loop: cmp x1, #1 /* compare r1 and 1 */ beq end /* branch to end if r1 == 1 */ and x3, x1, #1 /* r3 ← r1 & 1 */ cmp x3, #0 /* compare r3 and 0 */ bne odd /* branch to odd if r3 != 0 */even: mov x1, x1, ASR #1 /* r1 ← (r1 >> 1) */ b end_loopodd: add x1, x1, x1, LSL #1 /* r1 ← r1 + (r1 << 1) */ add x1, x1, #1 /* r1 ← r1 + 1 */ end_loop: add x2, x2, #1 /* r2 ← r2 + 1 */ b loop /* branch to loop */end: mov x0,x2 mov x8, 93svc 0复制代码
as -g -o collatz64.o collatz64.s
ld -o collatz64 collatz64.o
执行后结果如下:
echo $?
46
从这里我们可以看到32位的ARM汇编切换到64位其实是比较简单的。需要注意的是寄存器的变化和退出的方式。
更多相关文章
- 实现文件上下文管理(__enter__和__exit__)
- 流程控制之if判断
- 给我1万字,也讲不清Java内存排查。1万不行来2万~.~
- 想把Java代码写的更漂亮么?了解一下Try吧
- 解析Java横死之谜,气定神闲看花开花落
- 将java进程转移到“解剖台”之前,法医都干了什么?
- 工作累了,用java写个游戏吧!开源一款游戏引擎
- 一些好用的Java小库儿
- 牛气的JavaScript,让雪花算法成为空气