【问题标题】:ARM Assembly question (there is not enough register!)ARM 汇编问题(没有足够的寄存器!)
【发布时间】:2019-04-10 03:55:00
【问题描述】:

您好,我正在尝试编写进行模式搜索的代码,并将最流行的模式排名前 3 位,以及计算模式的次数。 我可以编写排名top2 模式的代码。但我不能做rank3。

(我是这样分配寄存器的)
R7 : top1 模式的计数
R8 : top1 模式
R10:top2 模式的计数
R11 : top2 模式

这是我的实际工作代码

void ex3(){
int result[4];

example3(0x00,0x100, 0x0, result);
sendstr("Top 1 pattern : ");
printDecimal(result[0]);
sendstr("\n");

sendstr("Top 1 pattern count : ");
printDecimal(result[1]);
sendstr("\n");

sendstr("Top 2 pattern : ");
    printDecimal(result[2]);
sendstr("\n");

    sendstr("Top 2 pattern count : ");
printDecimal(result[3]);
sendstr("\n");

}


PRESERVE8
AREA Ex3, CODE, READONLY

EXPORT  example3

example3
    STMFD       sp!,{r4-r9,lr}              
    MOV         R4, r2                          
    MOV         R6, R3
    MOV         R7, #0
    MOV         R8, #0

Loop2   
    MOV         r3, #0                          
    MOV         r9, r0

Loop
    LDRB        r5, [r9], #1                        
    CMP         r4, r5                          
    ADDEQ       r3, r3, #1                      
    CMP         r9, r1                          
    BLS         Loop
    CMP         R3, R7
    BLT         Com2




Com1

    MOVGT   R10,R7
    MOVGT   R11,R8
    MOVGT   R7, R3                          
    MOVGT   R8, R4
    B               Here

Com2
    CMP         R3,R10
    BLT         Here
    MOVGT   R10,R3
    MOVGT   R11,R4


    CMP         R4, #0XFF
    ADDLT       R4, R4, #1
    BLT         Loop2

    STR         r8, [r6]
    STR         r7, [r6,#4]

    STR         r11, [r6,#8]
    STR         r10, [r6,#12]


    LDMFD       sp!,{r4-r9,lr}

    MOV         PC, lr

    END

但是当我尝试具有相同逻辑的 rank3 代码时,只是以这种方式更改了寄存器分配

r7 count of top1 pattern  
r8 top1 pattern    

r9 top2 count  
r10 TOP2    

r11 top3 count  
r12 top3    

由于(在我看来)错误的寄存器分配(我需要更多的空寄存器...),它显示出奇怪的结果。解决注册不足的简单方法或正确方法是什么?

PRESERVE8
AREA Ex3, CODE, READONLY

EXPORT  example3

example3
    STMFD       sp!,{r4-r9,lr}              
    MOV         R4, r2                          
    MOV         R6, R3
    MOV         R7, #0
    MOV         R8, #0

Loop2   
    MOV         r3, #0                          
    MOV         r9, r0

Loop
    LDRB        r5, [r9], #1                        
    CMP         r4, r5                          
    ADDEQ       r3, r3, #1                      
    CMP         r9, r1                          
    BLS         Loop
    CMP         R3, R7
    BLT         Com2




Com1
    MOVGT   R11,R9
    MOVGT   R12,R10
    MOVGT   R9,R7
    MOVGT   R10,R8
    MOVGT   R7, R3                          
    MOVGT   R8, R4
    B               Here

Com2
    CMP         R3,R9
    BLT         Com3
    MOVGT   R11,R9
    MOVGT   R12,R10
    MOVGT   R9,R3
    MOVGT   R10,R4
    B               Here


Com3
    CMP         R3,R11
    MOVGT   R11,R3
    MOVGT   R12,R4


Here
    CMP         R4, #0XFF
    ADDLT       R4, R4, #1
    BLT         Loop2

    STR         r8, [r6]
    STR         r7, [r6,#4]

    STR         r10, [r6,#8]
    STR         r9, [r6,#12]
    STR         r12, [r6,#16]
    STR         r11, [r6,#20]


    LDMFD       sp!,{r4-r9,lr}

    MOV         PC, lr

    END

【问题讨论】:

    标签: assembly arm cpu-registers


    【解决方案1】:

    编译器将如何做到这一点?尝试编写一些 C 来做同样的事情,并让编译器生成汇编语言(如果您使用的是 GCC,它是 gcc -S)。这是学习有效汇编语言的好方法;并非编译器所做的所有事情都是最有效的,但它总是可以工作且合乎逻辑,并且如果禁用优化,应该相当容易遵循。

    如果您完全用完寄存器,您唯一的选择是使用堆栈进行本地存储,并根据需要推送和弹出寄存器,或者从该区域分配一些堆栈空间和LDR/STR 值按要求。但是,在您的情况下,您没有从函数中调用任何其他函数,因此没有理由避免使用被调用破坏的 r0-r3 或 r12。

    请注意,您提供的代码至少包含一个错误,因为您使用的是r10-r11,并且没有通过STMFD 和LDMFD 指令保留其内容。

    【讨论】:

    • 我喜欢推荐gcc -O1 至少,因为-O0 将所有内容都视为volatile 以进行一致的调试。每个语句之间的额外存储/重新加载会产生很多噪音,难以理解。 How to remove "noise" from GCC/clang assembly output? 有 x86 示例,但所有内容都适用于 ARM(godbolt.org 有 ARM gcc)
    • 可能是一个不错的电话,至少值得尝试与-O0进行比较。
    猜你喜欢
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多