Assembly 将C代码转换为ARM Cortex M3汇编代码
我得到了下面的c函数Assembly 将C代码转换为ARM Cortex M3汇编代码,assembly,arm,cortex-m3,Assembly,Arm,Cortex M3,我得到了下面的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-M3-assembler代码。
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-M3-assembler代码。我不是很擅长这个,如果我做得对,我没有合适的编译器来测试。但到目前为止,我所拥有的是
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
但我真的不确定这是否正确,但我不知道如何检查它……我只看到3个相当简单的问题:
BE _next ; if statement by "branch"-cmd
...
sub R0, R0, #1 ; loop counting
BLPL _for_loop ; pl = if positive or zero
,而不是BEQ
-条件代码始终为两个字母BE
本身不会更新标志-您需要后缀来表示,即SUB
SUBS
将进行分支和链接,从而覆盖您的回信地址-您需要BLPL
。实际上,BPL
无论如何都不会在这里进行汇编,因为根据经验,条件BLPL
需要一个BL
来设置它(当然,除非您的汇编程序足够聪明,能够自动插入一个)IT
R4
还有一个更普遍的问题-如果您与C代码交互,则必须在整个函数调用中保留原始值,然后恢复(R0
-R3
是指定的参数/暂存寄存器,可以自由修改)。但是,如果您处于纯汇编中,则不必遵循标准调用约定,因此可以更加灵活
现在,这是C代码的一种非常文字化的表示,并且没有充分利用指令集,尤其是索引寻址模式。汇编编程的一个吸引人之处是完全控制指令,那么我们如何才能让它值得一试呢 首先,让C代码看起来更像我们想要的程序集:
int main_compare (int nbytes, char *pmem1, char *pmem2){
while(nbytes-- > 0) {
if(*pmem1++ != *pmem2++) {
return 0;
}
}
return 1;
}
现在,这更清楚地表明了我们的意图,让我们玩编译器:
byte_cmp_loop PROC
; assuming: r0 = nbytes, r1=pmem1, r2 = pmem2
_loop:
SUBS R0, R0, #1 ; Decrement nbytes and set flags based on the result
BMI _finished ; If nbytes is now negative, it was 0, so we're done
LDRB R3, [R1], #1 ; Load from the address in R1, then add 1 to R1
LDRB R4, [R2], #1 ; ditto for R2
CMP R3, R4 ; If they match...
BEQ _loop ; then continue round the loop
MOV R0, #0 ; else give up and return zero
BX LR
_finished:
MOV R0, #1 ; Success!
BX LR
ENDP
这几乎减少了25%的指令!现在,如果我们引入另一个指令集功能-条件执行-并稍微放宽要求,而不破坏C语义,它会变得更小:
byte_cmp_loop PROC
; assuming: r0 = nbytes, r1=pmem1, r2 = pmem2
_loop:
SUBS R0, R0, #1 ; In C zero is false and any nonzero value is true, so
; when R0 becomes -1 to trigger this branch, we can just
; return that to indicate success
IT MI ; Make the following instruction conditional on 'minus'
BXMI LR
LDRB R3, [R1], #1
LDRB R4, [R2], #1
CMP R3, R4
BEQ _loop
MOVS R0, #0 ; Using MOVS rather than MOV to get a 16-bit encoding,
; since updating the flags won't matter at this point
BX LR
ENDP
汇编到一个可怜的22字节,这比我们开始时少了将近40%的代码:D好吧,下面是一些编译器生成的代码
arm-none-eabi-gcc -O2 -mthumb -c test.c -o test.o
arm-none-eabi-objdump -D test.o
00000000 <main_compare>:
0: b510 push {r4, lr}
2: 3801 subs r0, #1
4: d502 bpl.n c <main_compare+0xc>
6: e007 b.n 18 <main_compare+0x18>
8: 3801 subs r0, #1
a: d305 bcc.n 18 <main_compare+0x18>
c: 5c0c ldrb r4, [r1, r0]
e: 5c13 ldrb r3, [r2, r0]
10: 429c cmp r4, r3
12: d0f9 beq.n 8 <main_compare+0x8>
14: 2000 movs r0, #0
16: e000 b.n 1a <main_compare+0x1a>
18: 2001 movs r0, #1
1a: bc10 pop {r4}
1c: bc02 pop {r1}
1e: 4708 bx r1
arm-none-eabi-gcc -O2 -mthumb -mcpu=cortex-m3 -c test.c -o test.o
arm-none-eabi-objdump -D test.o
00000000 <main_compare>:
0: 3801 subs r0, #1
2: b410 push {r4}
4: d503 bpl.n e <main_compare+0xe>
6: e00a b.n 1e <main_compare+0x1e>
8: f110 30ff adds.w r0, r0, #4294967295 ; 0xffffffff
c: d307 bcc.n 1e <main_compare+0x1e>
e: 5c0c ldrb r4, [r1, r0]
10: 5c13 ldrb r3, [r2, r0]
12: 429c cmp r4, r3
14: d0f8 beq.n 8 <main_compare+0x8>
16: 2000 movs r0, #0
18: f85d 4b04 ldr.w r4, [sp], #4
1c: 4770 bx lr
1e: 2001 movs r0, #1
20: f85d 4b04 ldr.w r4, [sp], #4
24: 4770 bx lr
26: bf00 nop
您直接进入了nbytes——没有进行if nbytes>=0;比较
分支if equal的程序集是BEQ not BE和BPL,而不是BLPL。所以要解决这些问题,在一开始就对_进行无条件的分支,然后我想这就是你的代码
byte_cmp_loop PROC
; assuming: r0 = nbytes, r1=pmem1, r2 = pmem2
B _next
_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
BEQ _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
BPL _for_loop ; pl = if positive or zero
MOV R0, #1 ;
BX LR ; always return 1 here
ENDP
你打算在哪种体系结构上运行此代码?你能稍微整理一下代码吗,在指令的缩进和大小写方面保持一致?哦,我忘了提到体系结构…:/it's cortex m3。
byte_cmp_loop PROC
; assuming: r0 = nbytes, r1=pmem1, r2 = pmem2
B _next
_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
BEQ _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
BPL _for_loop ; pl = if positive or zero
MOV R0, #1 ;
BX LR ; always return 1 here
ENDP