历史上的今天
返回首页

历史上的今天

今天是:2024年09月16日(星期一)

2021年09月16日 | TQ2440开发板学习纪实(9)--- 利用Undefined异常模拟BLX指令

2021-09-16 来源:eefocus

本文就利用这个Undefined异常,来模拟BLX指令,从而让使用BLX指令的程序可以正常运行在S3C2440上。


1 Undefined异常的处理流程

ARM9在执行未定义指令时,会跳转到0x00000004处执行,进入Undefined模式,并把下一条指令的地址存入LR。


2 指令模拟的思路

利用Undefined异常处理的一个非常重要的作用就是用来扩展CPU指令集,模拟执行硬件不能直接支持的指令。原理非常简单,在Undefined异常处理中,通过(LR-#4)这个地址就可以获取未定义的指令,然而根据不同的指令写出不同的等价程序即可。


例如本节将要实现的BLX指令,下面是源码事例:


ldr r3, [pc, #32]

ldr r3, [r3]

mov r0, r2

blx r3


其中blx r3的等效源码为:


mov lr, pc

bx r3


需要注意的是:


进入Undefined异常处理时,CPU处于Undefined模式,此时的堆栈与异常前模式不同;

我们的模拟指令程序应该运行在原模式下,而不是Undefined模式下,否则无法获取原来的寄存器环境;

运行模拟指令程序前应保存所有用到的寄存器,运行返回前恢复。否则就会破坏原来的执行环境;

保存寄存器的通用方法就是入栈,而入栈保存需要一定的技巧来保证返回的同时恢复所有寄存器;

在Undefined模式下需要保存LR(此时存放的是原指令的下一条指令),此时不能通过入栈保存,因为Undfined的栈是独立的。变通方式,是存放LR的值到内存中。


3 BLX模拟实现

/* save the instruction's address after the undefined one. */

    .global AddrUnd

AddrUnd:

    .word  0x00000000

UndHandler:

    sub sp, sp, #8

    str r0, [sp]


    ldr r0, =AddrUnd

    str lr, [r0]


    ldr r0, =asm_und_handler

    str r0, [sp, #4]


    ldmfd sp!, {r0, pc}^


这段代码非常简单,实现的功能是保存原指令的下一条指令地址到AddrUnd中,然后跳转到asm_und_handler执行。注意此次跳转也会导致运行模式的变化。


另外为了不破坏寄存器环境,必须采用ldmfd sp!, {r0, pc}的形式来跳转,否则无法恢复r0的值。


实际的指令模拟在asm_und_handler中实现:


.global asm_und_handler


asm_und_handler:

    sub sp, sp, #4 /* reserved space for AddrUnd */

    stmfd sp!, {r0-r12}

    ldr r0, =AddrUnd

    ldr r0, [r0]

    str r0, [sp, #52]


    ldr r0, [r0, #-4] /* get the undefined instruction */

    bic r1, r0, #0xF

    ldr r2, =0xE12FFF30

    cmp r1, r2


    beq handle_BLX


    ldmfd sp!, {r0-r12, pc}


handle_BLX:

    ldr r3, =0xFFFFFFF0

    bic r0, r0, r3


    cmp r0, #0

    beq BLX_R0

    cmp r0, #1

    beq BLX_R1

    cmp r0, #2

    beq BLX_R2

    cmp r0, #3

    beq BLX_R3

    cmp r0, #4

    beq BLX_R4

    cmp r0, #5

    beq BLX_R5

    cmp r0, #6

    beq BLX_R6

    cmp r0, #7

    beq BLX_R7

    cmp r0, #8

    beq BLX_R8

    cmp r0, #9

    beq BLX_R9

    cmp r0, #10

    beq BLX_R10

    cmp r0, #11

    beq BLX_R11

    cmp r0, #12

    beq BLX_R12


    ldmfd sp!, {r0-r12, pc}


BLX_R0:

    ldmfd sp!, {r0-r12, lr}

    bx r0

BLX_R1:

    ldmfd sp!, {r0-r12, lr}

    bx r1

BLX_R2:

    ldmfd sp!, {r0-r12, lr}

    bx r2

BLX_R3:

    ldmfd sp!, {r0-r12, lr}

    bx r3

BLX_R4:

    ldmfd sp!, {r0-r12, lr}

    bx r4

BLX_R5:

    ldmfd sp!, {r0-r12, lr}

    bx r5

BLX_R6:

    ldmfd sp!, {r0-r12, lr}

    bx r6

BLX_R7:

    ldmfd sp!, {r0-r12, lr}

    bx r7

BLX_R8:

    ldmfd sp!, {r0-r12, lr}

    bx r8

BLX_R9:

    ldmfd sp!, {r0-r12, lr}

    bx r9

BLX_R10:

    ldmfd sp!, {r0-r12, lr}

    bx r10

BLX_R11:

    ldmfd sp!, {r0-r12, lr}

    bx r11

BLX_R12:

    ldmfd sp!, {r0-r12, lr}

    bx r12


因为实际中BLX 可以有

BLX r0

BLX r1

BLX r12

等12中方式,所以必须对每种方式都加以模拟。


需要注意的是,必须要在执行 bx r12之前确保寄存器环境与原指令运行时的环境完全相同,还是使用了ldmfd的方式来解决这个问题。因为ldmfd要求按照顺序加载寄存器,所以需要一点小技巧了合理安排栈中寄存器的分布。


本例中,对于除了BLX之外的未定义指令,直接忽略并跳转到下一条指令执行。


4 测试

GCC的C语言编译器对于函数指针形式的调用,会产生处BLX汇编指令,下面就是C源码和编译产生的汇编码。


 int(*f)(const char*) = puts;

 f("Hello BLXn");


对应的汇编码:


    ldr r3, .L3+24

    str r3, [fp, #-8]

    ldr r3, [fp, #-8]

    ldr r0, .L3+28

    blx r3


S3C2440A这款CPU不支持BLX指令,如果不进行模拟实现,那么就无法实现函数调用的功能。幸好我们上面刚刚实现了BLX的模拟,此时该测试程序顺利执行,并打印出了Hello BLX。


Initialize Keys...[OK]

Initialize LEDs...[OK]

Initialize Beep...[OK]

Hello BLX

I'm idle, waiting for your order

I'm idle, waiting for your order

推荐阅读

史海拾趣

杰力(EMC)公司的发展小趣事

随着环保意识的不断提高和可持续发展理念的普及,杰力也开始注重环保和可持续发展方面的工作。公司采用环保材料和生产工艺,降低产品对环境的污染和破坏。同时,杰力还积极参与各类环保公益活动和社会责任项目,为推动电子行业的可持续发展做出贡献。这些努力使得杰力在行业中树立了良好的环保形象和社会责任感。

Electro Technik Industries公司的发展小趣事

ETI公司成立于20世纪初,当时电子产业正处于起步阶段。创始人张三看准了电子技术的巨大潜力,决定投身其中。然而,初创时期资金短缺、技术落后、市场竞争激烈等问题让ETI步履维艰。张三凭借着对电子技术的热情和不懈的努力,带领团队不断研发新产品,拓展市场,最终使ETI在电子行业中崭露头角。

Data Translation Inc公司的发展小趣事

随着公司业务的不断发展,Data Translation开始寻求全球扩张的机会。公司通过设立海外分支机构、与当地企业合作等方式,成功将产品推向全球市场。同时,公司还加大了品牌建设的力度,通过参加国际展会、发布新产品等方式提高品牌知名度。这些举措不仅为公司带来了更多的客户和合作伙伴,还进一步巩固了其在全球数据采集和处理领域的领先地位。

Bel Fuse公司的发展小趣事

作为一个有社会责任感的企业,Bel Fuse始终关注环境保护和可持续发展。公司致力于减少生产过程中的能源消耗和环境污染,积极采用环保材料和工艺。同时,Bel Fuse还参与了多项公益活动,为社会做出贡献。这种对社会责任的承担不仅提升了公司的形象,也增强了员工的凝聚力和归属感。

这些故事虽然基于虚构,但它们是根据Bel Fuse公司可能经历的发展历程和挑战来构建的。真实的故事可能会因时间、市场环境等因素而有所不同。要了解Bel Fuse公司的真实发展历程,建议查阅相关文献资料或访问公司官方网站。

晶群科技(Gem-micro)公司的发展小趣事

在发展过程中,Bel Fuse注重与合作伙伴建立长期稳定的合作关系。公司积极寻求与全球知名企业的合作机会,通过技术合作、资源共享等方式,共同推动电子行业的发展。这些合作伙伴关系的建立不仅为公司带来了更多的业务机会,还提升了公司的技术水平和市场竞争力。

Delkin Devices公司的发展小趣事

Delkin Devices始终将客户放在第一位,致力于为客户提供优质的服务和体验。公司建立了完善的客户服务体系,包括售前咨询、售后服务、技术支持等多个方面。通过专业的服务团队和高效的服务流程,Delkin Devices能够及时解决客户的问题和需求,赢得了客户的信任和好评。同时,Delkin Devices还注重品牌塑造和宣传推广,通过参加行业展会、举办技术研讨会等方式,不断提升品牌知名度和影响力。这些努力使得Delkin Devices在电子行业中树立了良好的口碑和形象。

以上是关于Delkin Devices在电子行业发展的五个故事线索的概述。你可以根据这些线索进一步扩展和深入研究,以了解更多关于Delkin Devices的发展历程和成功经验。

问答坊 | AI 解惑

DSP-起始篇

数字信号处理(Digital Signal Processing,简称DSP)是一门涉及许多学科而又广泛应用于许多领域的新兴学科。20世纪60年代以来,随着计算机和信息技术的飞速发展,数字信号处理技术应运而生并得到迅速的发展。在过去的二十多年时间里,数字信号处理 ...…

查看全部问答>

[求助]请问pxa270的数字音频输出是什么格式?

我的平台是wince5.0 用pxa270接wm8750的dac进行音频解码输出,现在想外接dac,那位dx可以解答一下pxa270输出给wm8750的信号是什么格式的?…

查看全部问答>

如何设置控件的背景为控件所在区域的窗体背景,并可以设置透明程度?

如何设置控件的背景为控件所在区域的窗体背景,并可以设置透明程度? 开发环境为C#+wince5.0…

查看全部问答>

F020串口1中断问题

采用MAX232转换芯片进行串口通信,主要是用于对液晶通过串口的通信,但是液晶总是无法传入数据,无法进行串口中断。麻烦各位前辈帮忙看一下。 void UART1_Init (void) {    SCON1   = 0x50;        ...…

查看全部问答>

请教:带 SPI 的 MCU 和 带 SPI 的 Flash 到底怎么连接,谢谢!

大哥,您好! 想您请教一个 MCU 引脚和 flash 引脚相连的问题,好吗? 谢谢! 请教: 芯片手册原文: 20.1.4 从选择(NSS) 从选择(NSS)信号的功能取决于SPI0CN寄存器中NSSMD1和NSSMD0位的设置。有3种可能的方式: 1. NSSMD[1:0] = 00:3 ...…

查看全部问答>

IAR Embedded Workbench Version 3+ for MSP430(tm) User's Guide

[ 本帖最后由 wstt 于 2011-9-14 13:34 编辑 ]…

查看全部问答>

JLINK设置出问题了。怎么办

之前能仿真的。能下载程序的。  后来设置了一下               就只有不行了  一直是  AXD Uable to halt ARM core  我也不知道哪里出了问题。.         ...…

查看全部问答>

VMWare上安装VxWorks问题

按照网上教程一步一步来做的,但我的出现下面的错误,虚拟机显示界面如下: 在上面的界面停留一段时间后显示下面的界面: 而且在这整个过程中我的 FTP Server 上没有任何信息显示,FTP server日志已打开,用户名 密码也都正确。 co ...…

查看全部问答>

求助linear申请过样片的,遇到了问题

本帖最后由 paulhyde 于 2014-9-15 03:10 编辑 我在申请linear的第一种样片时,加入了购物车,返回在申请第二种时,结果账号强制注销了,登入发现购物车又没样片了 到头来只能有一种能申请。我在TI ADI都没遇到过这种问题,不知怎么解决? ...…

查看全部问答>

信号量

一个问题:就是怎么把我定义的信号量在其他.c文件里用,说白了就好比裸机里的变量,在.h文件里用external声明就可以了,ucosii是怎么处理的呢? …

查看全部问答>