我得到了下面的C函数
int main_compare (int nbytes, char *pmem1, char *pmem2){
for(nbytes--; nbytes>=0; nbytes--) {
if(*(pmem1+nbytes) - *(pmem2+nbytes) != 0) {
return 0;
}
}
return 1;
}
字符串
我想把它转换成ARM Cortex M3汇编代码。我真的不擅长这个,我没有合适的编译器来测试我是否做对了。但我现在所拥有的
byte_cmp_loop PROC
; assuming: r0 = nbytes, r1=pmem1, r2 = pmem2
SUB R0, R0, #1 ; nBytes - 1 as maximal value for loop counter
_for_loop:
ADD R3, R1, R0 ;
ADD R4, R2, R0 ; calculate pmem + n
LDRB R3, [R3] ;
LDRB R4, [R4] ; look at this address
CMP R3, R4 ; if cmp = 0, then jump over return
BE _next ; if statement by "branch"-cmd
MOV R0, #0 ; return value is zero
BX LR ; always return 0 here
_next:
sub R0, R0, #1 ; loop counting
BLPL _for_loop ; pl = if positive or zero
MOV R0, #1 ;
BX LR ; always return 1 here
ENDP
型
但是我真的不确定,如果这是正确的,但是我不知道如何检查它。
2条答案
按热度按时间5us2dqdw1#
我只看到三个相当简单的问题:
字符串
BEQ
,而不是BE
-条件代码始终为2个字母。SUB
不会单独更新标志-你需要后缀来说明这一点。SUBS
的值。BLPL
将分支和链接,从而覆盖您的返回地址-您需要BPL
。实际上,BLPL
不会在这里组装,因为在Thumb中,条件BL
需要一个IT
来设置它(当然,除非你的组装器足够聪明,可以自动插入一个)。编辑:当然,在原始代码和我下面的示例中使用
R4
还有一个更普遍的问题-如果您与C代码交互,则原始值 * 必须 * 在函数调用中保留并在之后恢复(R0
-R3
是指定的参数/临时寄存器,可以自由修改)。但是,如果你是在纯汇编语言中,你不一定需要遵循标准的调用约定,这样就可以更灵活。现在,这是C代码的一个非常字面的表示,并且没有最好地利用指令集-特别是索引寻址模式。汇编编程的吸引力之一是完全控制指令,那么我们如何才能使它值得我们花时间呢?
首先,让C代码看起来更像我们想要的程序集:
型
现在,这更清楚地显示了我们的意图,让我们玩编译器:
型
这几乎减少了25%的指令!现在,如果我们引入另一个指令集特性-条件执行-并稍微放宽要求,而不破坏C语义,它会变得更小:
型
汇编到一个微薄的22字节,这比我们开始时少了近40%的代码:D
o75abkj42#
这里有一些编译器生成的代码
字符串
有趣的是,thumb 2扩展似乎并没有让这一切变得更好,甚至可能更糟。
如果你没有一个编译器,那是否意味着你也没有一个汇编器和链接器?如果没有汇编器和链接器,编译和汇编机器代码将是大量的工作。那么你要如何将它加载到处理器中呢?
如果你没有一个ARM交叉编译器,你有编译器吗?你需要告诉我们更多关于你有什么和没有什么。如果你有一个web浏览器,你用来查找stackoverflow和发布问题,你可能可以下载代码源工具或https://launchpad.net/gcc-arm-embedded工具,并有一个编译器,汇编器和链接器(不必手工从c转换到asm)。
就你的代码而言,对于nbytes--减去1是正确的,但是你没有将nbytes值与零进行比较,看看你是否根本不需要做任何事情。
在伪代码中
型
你直接去了nbytes--没有做if nbytes>=0;比较
如果等于,则分支的程序集是BEQ而不是BE和BPL而不是BLPL。所以修复这些,在一开始做一个无条件分支到_next,我想这就是你编码的。
型