汇编调用其他程序的子程序_基于LiteOS Studio & Qemu零成本学习ARM 汇编——0x04 聚沙成塔...

f3cd410cce127f45c512a529af6886ed.png

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

本系列的其他文章

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

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

LiteOS Studio零成本学习ARM汇编 三 再上层楼

基于LiteOS Studio & Qemu零成本学习ARM 汇编——0x04 聚沙成塔

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

当程序包含多个汇编文件的时候,每个文件编译为单独的对象文件,链接器linker链接这些对象文件为一个单独的可执行文件。如下图:

0cdddc17fd73dce33d7b35ac42ca8f0a.png

链接器的作用

在链接各个对象文件的时候,链接器完成如下操作:

Symbol Resolution 符号解析

Relocation重定位

这些信息不再详细描述,请阅读参考资料部分,完成对链接器如何进行符号解析、重定位。

0x01 链接器linker示例代码

数组求和的示例代码分解成2个独立的汇编源文件,sum-sub.s包含sum子程序,main.s 负责传递参数,调用sum子程序,完成数组求和。

源程序代码如下:

main.s:

.text
	.global  _start
        b _start                @ 跳过数据段
arr:    .byte 10, 20, 25        @ 只读的bytes数组
eoa:                            @ 紧接着bytes数组的地址,eoa: End Of Array + 1
        .align_start:
        ldr   r0, =arr          @ r0 = &arr        ldr   r1, =eoa          @ r1 = &eoa        bl    sum               @ 调用求和子程序sum subroutine
stop:   b stop

sum_sub.s:

@ Args参数
        @ r0: 数组的开始地址        @ r1: 数组的结束地址        @        @ Result结果        @ r3: 数组的求和结果        .global sum
sum:    mov   r3, #0            @ r3 = 0
loop:   ldrb  r2, [r0], #1      @ r2 = *r0++    ; 获取数组元素,r0然后指向下一个元素
        add   r3, r2, r3        @ r3 += r2      ; 求和,保存到r3寄存器
        cmp   r0, r1            @ if (r0 != r1) ; 检查是否到数组的末尾
        bne   loop              @    goto loop  ; Loop
        mov   pc, lr            @ pc = lr       ; 完成后 返回调用函数处

GDB 单步调试:

https://gitee.com/huawei_liteos_studio/arm_assembly/tree/master/Linker检出示例代码工程,使用LiteOS Studio打开工程。编译、开始调测,我们打开build目录下面的asm文件,并且分栏展示,F10单步调试,单步调试如之前操作。调试调试运行到main.s 第12行 “bl sum”调用子程序的时候,注意观察PC、LR寄存器值。可以看到调用子函数的时候,会把子函数的函数首地址赋值给lr链接寄存器,此处为0x20.等子程序执行完毕,会使用指令“mov pc, lr ”,把lr寄存器值赋值给pc。进行调测,会执行函数的外的下一个指令。

界面如下:

7a2087c8b4e33e172a5fd84a6def629b.png

0x02 链接脚本linker script

如前文所述,链接器负责section区段的合并和替换。程序员可以通过链接器脚本文件控制section如何合并,以及放在内存的位置。一个简单的链接器脚本如下:

SECTIONS { ❶
        . = 0x00000000; ❷
        .text : { ❸                abc.o (.text);                def.o (.text);
        } ❹}

SECTIONS命令用于指明section如何合并、以及合并到内存的位置。

点符号. 表示位置计数器location count

3、4表示输入文件abc.o def.o的.text区段合并到输出文件的.text区段。链接器脚本可以使用*通配符,如下:

SECTIONS {
        . = 0x00000000;
        .text : { * (.text); }
}

如果程序包含.data区段,脚本示例如下:

sum-data.lds:

SECTIONS {
         . = 0x00000000;
         .text : { * (.text); }         . = 0x00000400;
         .data : { * (.data); }
}

.text区段开始于0x0,.data区段开始于0x400. 如果位置计数器不指定值,.text .data在内存中的位置毗连。

0x03 链接脚本linker script示例代码

修改数组求和的示例代码来演示如何使用链接器脚本文,控制程序的.text、.lianjdata区段。

唯一的变化是,数组现在在.data 区段。烦人的跳转指令跳过data数据不再需要。链接器脚本文件作为参数传递给链接器,详细了解示例工程代码中的makefile。

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

GDB 单步调试:

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

4a4e80dff7156cd1281a7349e69782c0.png

linker script file debug

0x04 参考资料

http://www.bravegnu.org/gnu-eprog/linker.html

http://www.bravegnu.org/gnu-eprog/lds.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值