8086汇编4位bcd码_LiteOS Studio零成本学习ARM汇编 三 再上层楼

免责声明:本文提供的所有内容仅供学习、分享与交流,不保证内容的正确性,亦不对内容可能带来的风险担责。如若转载,请署名以及注明原始出处。本文仅代表个人的立场和观点,并不代表任何公司或组织。

本系列的其他文章

LiteOS Studio零成本学习ARM汇编 一 环境搭建

LiteOS Studio零成本学习ARM汇编 二 初识谢娘

基于LiteOS Studio & Qemu零成本学习ARM 汇编——0x03 再上层楼

下面的全部操作仅适用Window 10 64bits 环境。

本文会基于数组求和、计算字符串长度两个例子来熟悉更多的汇编器指令assembler directives。

0x01 数组求和

汇编程序代码如下,该段代码引入了2个汇编器指令.byte、.align:

        .text      .global  _startentry:  b _start                  @ 跳过数据段arr:    .byte 10, 20, 25        @ 只读的bytes数组eoa:                                   @ 紧接着bytes数组的地址,eoa: End Of Array + 1        .align_start:        ldr   r0, =eoa          @ r0 = &eoa 取eoa标签所在的地址        ldr   r1, =arr            @ r1 = &arr 取arr标签,字节数组的首地址        mov   r3, #0            @ r3 = 0 赋值0loop:   ldrb  r2, [r1], #1      @ r2 = *r1++ 取数组的值,然后指向下一个数组元素        add   r3, r2, r3         @ r3 += r2  对获取的值进行求和        cmp   r1, r0            @ 判断是否 (r1 != r2)        bne   loop              @    goto loopstop:   b stop

.byte指令:

指令.byte {,} … 定义一个或多个Byte,并为之分配连续的内存空间。参数可以是整形字面量,二进制(0b|0B前缀)、八进制(0前缀)、十进制,或十六进制(0x|0X前缀),参数也能是字符常量,单引号括起来字符常量。

.align 指令:

ARM指令占用32位,4 bytes的内存,第一个byte的地址必须是4的倍数。为了满足这个,.align指令可以填充字节来满足下一个字节的地址是4的倍数。当字节、半字节插入的时候,会需要使用.align对齐。如下图所示,汇编代码的第7行使用了.align指令,对应的反汇编文件第15行填充空字节。否则_start 指令从00000007处开始,不满足4的倍数。填充一个字节后,从00000008处开始,下一指令_start的第一个字节满足4的倍数。

c59c11871291b31b0dda47734b4ce5d1.png

.align指令

GDB 单步调试:

https://gitee.com/huawei_liteos_studio/arm_assembly/tree/master/SumAnArray检出示例代码工程,使用LiteOS Studio打开工程。编译、开始调测,我们打开build目录下面的asm文件,并且分栏展示,F10单步调试,单步两次后,界面如下:

执行完毕第9行汇编代码,从反汇编文件中可以看到eoa的地址即0x00000007赋值给r0寄存器。

执行完毕第10行汇编代码,从反汇编文件中可以看到arr字节数组的首地址即0x00000004赋值给r1寄存器。

24bfd6c35602df4bb1a317d1808fe382.png

F10 GDB 单步调试

执行完毕第12行汇编代码,从r1寄存器的值0x00000004位数组的第一个地址,该地址对应的数值为0x0a即10,放入寄存器r2。 r1寄存器指向下一个字节数组的地址。

执行完毕第13行汇编代码,依次对数组元素进行求和,放入r3寄存器。

7d7f667157d8eadb7bf12d931817ce9b.png

F10 GDB调试数组求和

执行完毕第14行汇编代码,比较r0、r1寄存器,r0为数组末尾元素的下一个地址。r1指向字节数组的元素地址,读取数组元素后,会指向下一个地址,读完所有的数组元素后r0、r1元素都会指向0x00000007这个地址。当cmp指令条件成立,跳出loop循环。依次读取的数组元素为0x0a、0x14、0x19,即 10、20、25,从反汇编文件11-12行中可以看出来。

0x02 计算字符串长度

汇编程序代码如下,该段代码引入了2个汇编器指令.asciz、.equ:

        .text      .global _start        b _startstr:    .asciz "Hello World"        .equ   nul, 0        .align_start:  ldr   r0, =str          @ r0 = &str取字符串的地址        mov   r1, #0loop:   ldrb  r2, [r0], #1      @ r2 = *(r0++)        add   r1, r1, #1        @ r1 += 1        cmp   r2, #nul          @ if (r1 != nul)        bne   loop              @    goto loop        sub   r1, r1, #1        @ r1 -= 1stop:   b stop

.asciz指令

.asciz指令接收字符串字面量作为参数,字符串字面量是双引号包含的字符序列,这些会被汇编到连续的内存地址。汇编器自动在字符串的末尾插入nul字符(0)。.ascii指令和.asciiz指令一样,区别是.ascii指令不会自动在末尾增加nul。

.equ指令

汇编器维护一个符号表,来映射标签名称和内存地址。当汇编器遇到标签定义的时候,会在符号表中建立一个入口。当汇编器遇到标签引用时,替换标签为从符号表中对应的地址。

使用汇编器指令.equ,会在符号表中增加一个条目,映射名称和值,这个值不需要一定是地址。当汇编器遇到这些名称的时候,替换为相应的值。这些标签名称、equ定义的名称被称为符号名称。

指令的语义如下:

.equ name, expression

注意:.byte、.equ指令本身不分配内存,他们只在符号表中创建条目。

GDB 单步调试:

https://gitee.com/huawei_liteos_studio/arm_assembly/tree/master/StringLength检出示例代码工程,使用LiteOS Studio打开工程。编译、开始调测,我们打开build目录下面的asm文件,并且分栏展示,F10单步调试,单步调试如之前操作。String字符串在内存的存储可以通过反汇编进行查看,界面如下:

1cc57bd896f09b96a53591693e32218b.png

字符串存储

0x03 参考资料

http://www.bravegnu.org/gnu-eprog/asm-directives.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值