ARM程序集比较两个字符(ascii)

时间:2018-10-25 14:36:46

标签: assembly arm

test:
    ldr r0, [r1, #4]
    bl printf

    ldr r2, [r1, #4]
    ldrb r0, [r2], #1

    cmp r0, #32
    beq test
#32是空格的十进制ASCII码

使用以下代码编译代码

arm-none-eabi-gcc a.s -T generic-hosted.ld

然后运行

arm-none-eabi-run a.out "abcde"
arm-none-eabi-run a.out " bcde"

我想第一个命令将打印一次“ abcde”,第二个带空格的命令应该打印两次“ bcde”。但是我两次都打印一次,这是什么问题?

2 个答案:

答案 0 :(得分:1)

printf可能会修改r0,r1,r2,r3和r12。

您将需要使用调用保留寄存器(并在返回之前将其还原),或将值保存在堆栈中。

答案 1 :(得分:0)

Timothy Baldwin's answer是准确的,但我认为我会对此做一点扩展。 ARM应用程序二进制接口(ABI),尤其是procedure call standard,定义了如何跨过程调用边界对待每个寄存器。

总而言之,r0-r3用于传递参数和返回值,并且必须由调用方与“内部过程调用暂存寄存器” r12一起保存。所有其他通用寄存器必须由 callee 保存。因此,如果您要用汇编语言编写自己的函数,则在调用任何其他函数的同时,除了r4-r11lr)之外,还必须推送您使用的r14中的任何一个必须确保您对堆栈的使用是“平衡的”,以便spr13)的退出值与进入的值相同。

大多数编译器(至少在禁用优化的情况下)会在推入被调用者保留寄存器之后立即从开始将所有函数参数移出r0-r3来生成满足这些要求的代码;通过在返回之前将任何返回值移动到r0中;并且仅通过使用r0-r3来在函数执行过程中将参数传入和传出被调用函数。

此外,跨不同目标文件(即,不同源文件)中的函数,堆栈必须是8字节对齐的,因此,始终保持8字节对齐是一个好习惯,因为它很容易做到并且是免费的(出于与缓存相关的原因)。为此,请确保每次与堆栈的交互(每个PUSHPOP)都涉及偶数个寄存器,并在必要时推入并弹出其他寄存器以构成偶数。