• 2.汇编代码的简单实现


    2.汇编代码的简单实现

    1. 使用汇编的原因很简单,就是汇编代码的高效。在机器启动的时候,利用汇编的高效,对硬件进行初始化,为加载内核,提供条件。
    2. 目前常用的ARM汇编指令有两种:

      *ARM标准汇编:适用于ARM公司的汇编器,适合在Windows平台下使用。

      *GNU汇编:使用与GNU交叉编译工具链中的汇编器,适合于Linux平台开发。

    3.汇编程序框架:注意下面的操作环境是Redhat 6.4 + eclipse C/C++ +CDT插件。

    汇编代码的基本框架

    汇编用到的地方,启动代码,效率要求高效的地方。

    上面是启动代码的框架。

    下面搭建框架:

    start.S:

    .text

    .global _start

    _start:

        mov r2,#2

        mov r3,#3

    Makefile:

    all : start.o

        arm-linux-ld -Tgboot.lds -o start.elf $^

    %.o : %.S

        arm-linux-gcc -g -o $@ $^ -c

    clean:

        rm *.o *.elf

    简单工程的运行的结构:

    链接器脚本:

    Gboot.lds:

    OUTPUT_ARCH(arm)

    ENTRY(_start)

    SECTIONS {

        . = 0x50008000;

        

        . = ALIGN(4);

        .text :

        {

        start.o (.text)

        *(.text)

        }

        . = ALIGN(4);

        .data :

        {

        *(.data)

        }

        

        . = ALIGN(4);

        bss_start = .;

        .bss :

        {

        *(.bss)

        }

        bss_end = .;

    }

    运行的结果:

    接下来是汇编代码的操作实现:

    mov r1,#6

    mov r2,r1

    mov r3,#10

    @mvn:传值取反的值

        mvn r0,#4 @r0:4取反变为-5

        mvn r1,#0b111000

        mvn r2,r1 @r2:0b111000

    Sub的实例:

    Add的实例:

    当然,我们也可以在执行的时候指定参数的值:如下图,我们指定了r0=44,r2=66.

    运行了之后:

    And的实例;

    Bic的实例:第三个数是源码,源码位为1的,对应的位清0,源码位是0的,对应的位不变。

    从上面的执行结果看到,r1的最高位,和最低两位的1,对应源码位的值都是1,所以,被清0,中间四位,对应源码的四个0,保持不变1010.所以最后输出了0b101000.

    1. 比较指令

      Cmp指令的操作:比较的结果不会保持,回去影响cpsr对应的位:N或Z位。

      我们可以看到r1-1=1是正数,cpsr的最高位四位2=0010,N,Z位都是0.

      这里r1-3=-1,cpsr的最高四位8=1000,即是N位被置为1,表示结果是负数。

      这里r1-2=0,cpsr的次高位被置为1,表示两个数相等。

      Txt指令的操作:测试位、按位与,结果为0 ,Z位被置为1,结果不为0,Z位置为0

      按位与之后的值不为0,所以cpsr的Z位不会被置为1.

      按位与之后的结果是为0的,所以cpsr的Z位被置1.结果高四位的值是4.

    2. 跳转指令:

      B指令:

      上面的例子中,gt表示大于的时候跳转,6>5所以跳转到标签branch1处执行。不会执行add r3,r1,r2.

      上面,跳转的条件不成立,顺序执行,不跳转。但是会顺序执行,所以加个b end跳转到end,执行空操作。

      Bl:带链接的跳转:

      Lr:

      反汇编的代码:

      由上面看到lr保存的是bl返回来后的下一条地址,把他赋值给pc指针进行跳转。

    3. 移位指令:
    4. Lsl左移指令:

      11左移两位:1100

    5. ror循环右移:

      循环右移,最低位的1,被循环移动到了最高位。

    6. 程序状态字访问指令。

      在GNU汇编中,我们不允许上面的 指令来操作访问我们的程序字状态寄存器指令,所以我们需要将他们的值移出,再进行操作访问,修改等,操作完还要移进去。所以就设计到两个指令:MSR和MRS指令。搬出mrs,搬回去msr。

      执行了之后:

      最后:

      我们就是得通过上面的操作来改变cpsr里的值的。

    7. 存储器访问指令:

      上面的都是核里面的指令,内存是通过存储器访问质指令。

      Ldr指令:内存保存到寄存器

      Str指令:寄存器保存到内存。

      我们把r1设置成了开发板内存的地址,如上图,接下来在memory里创建一个监控的地址:

      接下来看看运行了上面的指令后的变化:如下图,我们的0xff已经被保存到了0x50008000.

      下面是ldr:

      R2的值就是存进r0里的值,被取出来了。

      这个汇编操作的工程代码:

      .text

      .global _start

      _start:

          @ldr和str的操作

          mov r0,#0xff

          str r0,[r1]

          ldr r2,[r1]

          @程序状态字寄存器访问

          mrs r0,cpsr

          orr r0,#0b100

          msr cpsr,r0

          @ror:循环右移

          mov r1,#0b11

          mov r1,r1,ror#1

          @lsl:左移

          mov r1,#0b11

          mov r1,r1,lsl#2

          @bl指令:带链接跳转

          bl func1

          @b指令:

          mov r1,#6

          mov r2,#7

          cmp r1,r2

          bgt branch1@gt表示大于的时候跳转

          add r3,r1,r2

          b end

      func1:

          mov r1,#23

          mov pc,lr@函数的返回,固定格式。

      branch1:

          sub r3,r1,r2

      end:

          nop

          @tst指令:

          mov r1,#0b101

          tst r1,#0b01

          mov r1,#0b101

          tst r1,#0b10

          @cmp指令的操作:

          mov r1,#2

          cmp r1,#1

          mov r1,#2

          cmp r1,#3

          mov r1,#2

          cmp r1,#2

          @bic:位清除指令

          mov r1,#0b1101011

          bic r2,r1,#0b1000011

          @and的用法:逻辑与

          mov r1,#5

          and r2,r1,#0

          mov r1,#5

          and r2,r1,#1

          @add:加法:

          add r1,r0,r2

          @sub:减法,注意被减数不能是立即数

          mov r2,#4

          sub r0,r2,#2

          mov r1,#3

          sub r3,r1,r0

          @这是注释,mov指令

          mov r1,#6

          mov r2,r1

          mov r3,#10

          @mvn:传值取反的值

          mvn r0,#4 @r0:4取反变为-5

          mvn r1,#0b111000

          mvn r2,r1 @r2:0b111000

    我是一只菜鸟!FORFISH!
  • 相关阅读:
    代码书写的细节
    php中的正则函数主要有三个-正则匹配,正则替换
    2个比较经典的PHP加密解密函数分享
    淘宝运营中的6大致命误区,你犯过么?
    30分钟教你写出10分的淘宝标题
    超全的web开发工具和资源
    转化率不好?告诉你转化飙秘诀
    帮你店铺日销千单的20个淘宝小技巧
    不刷单,中小卖家如何提升店铺流量?
    使用Flexible实现手淘H5页面的终端适配
  • 原文地址:https://www.cnblogs.com/FORFISH/p/4199591.html
Copyright © 2020-2023  润新知