Linux教程

第12部分- Linux ARM汇编 控制指令

本文主要是介绍第12部分- Linux ARM汇编 控制指令,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

ARM的汇编控制如下:

  • IF、ELSE及ENDIF
  • WHILE及WEND
  • MACRO及WEND
  • MEXIT

 

32位示例

完成1+2+…+22。

.text
.global main
main:
    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 loop
end:
    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 loop
end:
    mov x0, x1       /* r0 ← r1 */
    mov x8, 93
	svc 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 main
main:
    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_loop
odd:
    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_loop
odd:
    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, 93
	svc 0
复制代码

as -g -o collatz64.o collatz64.s

ld -o collatz64 collatz64.o

执行后结果如下:

echo $?

46

从这里我们可以看到32位的ARM汇编切换到64位其实是比较简单的。需要注意的是寄存器的变化和退出的方式。


这篇关于第12部分- Linux ARM汇编 控制指令的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!