Assembly ARM中的编码键

Assembly ARM中的编码键,assembly,arm,Assembly,Arm,这是一个叫做armkey的ARM程序,它从文件key.in中读取一行ASCII文本,其中包含可打印字符和控制字符00h-7Fh,并将其转换为输入字符串。读取字符串ARM SWI将删除任何行尾指示或字符,并将其替换为单个二进制0。如果没有更多的行,读取字符串ARM SWI将返回读取字节数的零计数 我的代码是有效的,但是有人能建议一些方法来提高效率吗?例如,我曾考虑使用ORR和and进行比较,但我似乎无法使其工作并一直运行在无限循环中。感谢您的帮助 ;--------------------

这是一个叫做armkey的ARM程序,它从文件key.in中读取一行ASCII文本,其中包含可打印字符和控制字符00h-7Fh,并将其转换为输入字符串。读取字符串ARM SWI将删除任何行尾指示或字符,并将其替换为单个二进制0。如果没有更多的行,读取字符串ARM SWI将返回读取字节数的零计数

我的代码是有效的,但是有人能建议一些方法来提高效率吗?例如,我曾考虑使用ORR和and进行比较,但我似乎无法使其工作并一直运行在无限循环中。感谢您的帮助

    ;------------------------------------------------;
    ; File:     armkey.s
    ;
    ; Function: This program reads a line of ASCII text
    ;           from a file and formats the output into 
    ;           key.out 
    ;
    ; Author:
    ;
    ; Changes:  Date        Reason
    ;           -------------------------------------
    ;           04/05/2018  Original Version
    ;----------------------------------------------------

    ;----------------------------------
    ; Software Interrupt values
    ;----------------------------------      
            .equ SWI_Open,  0x66     ;Open  a file
            .equ SWI_Close, 0x68     ;Close a file
           .equ SWI_PrStr, 0x69     ;Write a null-ending string
           .equ SWI_RdStr, 0x6a     ;Read a string and terminate with null char
           .equ SWI_Exit,  0x11     ;Stop execution
    ;----------------------------------

             .global   _start
             .text

    _start:
    ;----------------------------------
    ; open input file
    ; - r0 points to the file name
    ; - r1 0 for input
    ; - the open swi is 66h
    ; - after the open r0 will have the file handle
    ;----------------------------------
             ldr  r0, =InFileName     ;r0 points to the file name
             ldr  r1, =0              ;r1 = 0 specifies the file is input
             swi  SWI_Open            ;open the file ... r0 will be the file 
    handle
             ldr  r1, =InFileHandle   ;r1 points to handle location
             str  r0, [r1]            ;store the file handle
    ;----------------------------------


    ;----------------------------------
    ; open output file
    ; - r0 points to the file name
    ; - r1 1 for output
    ; - the open swi is 66h
    ; - after the open r0 will have the file handle
    ;---------------------------------- 
             ldr  r0, =OutFileName    ;r0 points to the file name
             ldr  r1, =1              ;r1 = 1 specifies the file is output
             swi  SWI_Open            ;open the file ... r0 will be the file 
    handle
             ldr  r1, =OutFileHandle  ;r1 points to handle location
             str  r0, [r1]            ;store the file handle
    ;----------------------------------


    ;----------------------------------
    ; read a string from the input file
    ; - r0 contains the file handle
    ; - r1 points to the input string buffer
    ; - r2 contains the max number of characters to read
    ; - the read swi is 6ah
    ; - the input string will be terminated with 0  
;----------------------------------                          ;
_read:       
         ldr  r0, =InFileHandle   ;r0 points to the input file handle
         ldr  r0, [r0]            ;r0 has the input file handle
         ldr  r1, =InString         ;r1 points to the input string
         ldr  r2, =80            ;r2 has the max size of the input string
         swi  SWI_RdStr           ;read a string from the input file
         cmp  r0,#0               ;no characters read means EOF
         beq  _exit               ;so close and exit
;----------------------------------
;// Implement key here

;----------------------------------
; Move the input string to the output string
; This code uses post increment of the input pointer,
; but not for the output pointer ... just to show both techniques
;----------------------------------
         ldr  r0, =InString       ;r0 points to the input  string
         ldr  r1, =OutString      ;r1 points to the output string
_loop:                            ;

        ldrb r2, [r0], #1        ;get the next input byte


        cmp   r2, #0x20   ; Was the character a space

        beq   _output             ; Print it
        cmp   r2, #0x00             ; Is the character a 0 
        beq  _output                ;Output it
_lower: 


        cmp   r2, #0x41           ; Check if the charactet is nor a letter
        blt     _loop             ; Throw out the character if nor a letter
        cmp   r2, #0x5a           ; Every letter will be less than Z
        ble   _output             ; If the character is valid output it
        sub   r2, r2, #0x20       ; Subtract ing 20 seitches an upper case letter to lower
        b     _lower              ; Check to see if lowercase letter



_output:        
         strb r2, [r1]            ;store it in the output buffer
         cmp  r2, #0x00             ;was it the null terminator
         beq  _finloop            ;yes ... exit
         add  r1, r1, #1          ;no  ... advance the output pointer
         b    _loop               ;loop
_finloop:                         ;
;----------------------------------


;----------------------------------
; Write the outputs string
; Then writes a CR LF pair
;----------------------------------

         ldr  r0, =OutFileHandle  ;r0 points to the output file handle
         ldr  r0, [r0]            ;r0 has the output file handle
         ldr  r1, =OutString      ;r1 points to the output string
         swi  SWI_PrStr           ;write the null terminated string

         ldr  r1, =CRLF           ;r1 points to the CRLF string
         swi  SWI_PrStr           ;write the null terminated string
         bal  _read               ;read the next line
;----------------------------------




;----------------------------------
; Close input and output files
; Terminate the program
;----------------------------------
_exit:                            ;
         ldr  r0, =InFileHandle   ;r0 points to the input  file handle
         ldr  r0, [r0]            ;r0 has the input file handle
         swi  SWI_Close           ;close the file
                                  ;
         ldr  r0, =OutFileHandle  ;r0 points to the output file handle
         ldr  r0, [r0]            ;r0 has the output file handle
         swi  SWI_Close           ;close the file
                                  ;
         swi  SWI_Exit            ;terminate the program
;----------------------------------


         .data
;----------------------------------
InFileHandle:  .skip 4            ;4 byte field to hold the input  file handle
OutFileHandle: .skip 4            ;4 byte field to hold the output file handle
                                  ;
InFileName:    .asciz "KEY.IN"   ;Input  file name, null terminated
                                  ;
InString:      .skip 128         ;reserve a 128 byte string for input
OutString:     .skip 128         ;reserve a 128 byte string for output
                                  ;
CRLF:          .byte 13, 10, 0    ;CR LF
                                  ;
OutFileName:   .asciz "KEY.OUT"  ;Output file name, null terminated
;----------------------------------


         .end
输出是

ABCDEFGHIJKLMNOPQRSTUVWXYZ 
ABCDEFGHIJKLMNOPQRSTUVWXYZ

在这段代码中,您将把大部分时间花在I/O上,但我们可以想象缓冲区非常大,因此与SWI的开销相比,内存复制非常重要

首先,您可以根据与NEON SIMD指令的比较,对数组进行左打包过滤。但是手臂少了一些。e、 g.pmovmskb将向量比较结果转换为整数寄存器中的位掩码,在该寄存器中,您可以将其用作表索引来查找洗牌掩码。然后点击查看输出指针的前进距离。我甚至不知道如何使用NEON高效地实施strchr:/

尽管如此,如果您一次可以处理多个字节的话,通过这种方式仍然可以实现较大的加速。无分支也很好,可以避免分支预测失误

您不需要单独的输出缓冲区;您可以就地筛选阵列。搜索第一个“”,然后在同一缓冲区内运行src和dst指针。src总是领先于dst,对于您跳过的每个字符,src都会领先于dst。但距离不太远,所以在存储时缓存中不是热的,所以可以避免所有存储到冷缓存线的所有权读取流量。您所接触的内存总量约为一半,因此从缓存中移出的数据更少

重新排列你的循环,没有b回到顶部。有时,这需要倾斜循环,因此您必须剥离上一次迭代的一部分,并在循环后重复一些循环体,并且您必须在进入第一次迭代之前进行一些设置,或者在进入时跳到循环的中间

ldr r0,=InFileHandle:使用保留调用的寄存器跨swi指令在寄存器中保留指向数据区域的指针。在功能开始/结束时,使用push/pop保存/还原它。然后,不需要单独构造每个指针,只需对不同的数据项使用具有不同偏移量的加载。e、 g.ldr r0,[r4,InFileHandle Base],如果这是正确的语法

或者,例如,在具有单独输入/输出缓冲区的当前代码中

     ldr  r0, =InString       ;r0 points to the input  string
     ldr  r1, =OutString      ;r1 points to the output string
您可以将第二条指令替换为add r1、r0、128,这比ALU指令更便宜,而不是来自文字池的PC相对负载,或者汇编程序决定为您构造一个常量

或者更好的方法是保存/恢复两个寄存器,这样您就可以将两个文件描述符都保存在寄存器中,而不是为它们保留任何静态存储空间