【问题标题】:ARM Assembly - Change input file to only include capital letters and spaces, write to outputARM 程序集 - 将输入文件更改为仅包含大写字母和空格,写入输出
【发布时间】:2015-07-25 23:15:11
【问题描述】:

我现在正在学习 x86 课程,我们有一个 ARM 程序集作业,它是我们所做的 x86 作业的副本。基本上它从文件中读取,将小写字母更改为大写,并保留空格。所以它只写大写字母(如果是小写则更改小写字母),并复制空格,同时去掉数字和字符。我们只使用十六进制字符 00h-7F(即使我们拥有的最低可用字符是 0x20)。我试图将我的代码从 x86 转换为 ARM,但它只是直接通过,没有写入输出。任何想法为什么,以及如何解决它?

我写了标有“检查是否小写”“检查是否大写”和“检查是否空格”的部分

;---------------------------------------------------------------------
; File:     ARMkey.s
;
; Function: This program copies an ASCII file
;           It assumes the file uses CR/LF as the end of line sequence
;           - It opens an input file named key.in
;           - It opens an output file named key.out
;           - It reads one line of text from the input file.
;           - It writes that one line to the output file, only using chars 00h-7Fh then a CR LF
;           - It loops until it reaches end of file
;           - It closes the input and output file
;
;
;---------------------------------------------------------------------


;----------------------------------
; 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, =String         ;r1 points to the input string
         ldr  r2, =128            ;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
;----------------------------------

;----------------------------------
; Check if Lower Case Letter
;----------------------------------

     cmp    r1, #0x61              ;check against lowercase a
     blt    _notlower              ;if less go to notlow
     cmp    r1, #0x7A              ;check against lowercase z
     bgt    _notlower
     sub    r1, r1, #0x14          ;Make letter uppercase
     bal    _read

;----------------------------------
; Check if Upper Case Letter
;----------------------------------

_notlower:
     cmp    r1, #0x41             ;dl < A
     blt    _space                ;jump to not letter
     cmp    r1, #0x5A             ;dl > Z
     blt    _space                ;jump to not letter

;----------------------------------
; Check if Space
;----------------------------------

_space:
     cmp    r1, #0x20             ; r1 = space?
     beq    _read                 ; yes, get new letter


;----------------------------------
; Write the outputs string
;----------------------------------
_write:                           ;
         ldr  r0, =OutFileHandle  ;r0 points to the output file handle
         ldr  r0, [r0]            ;r0 has the output file handle
         ldr  r1, =String         ;r1 points to the output string
         swi  SWI_PrStr           ;write the null terminated string
                                  ;
         ldrb r1, [r1]            ;get the first byte of the line



         cmp  r1, #0x1A           ;if line was DOS eof then do not write CRLF
         beq  _read               ;so do next read
                                  ;
         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
                                  ;
String:        .skip 128          ;reserve a 128 byte string
                                  ;
CRLF:          .byte 13, 10, 0    ;CR LF
                                  ;
OutFileName:   .asciz "KEY.OUT"  ;Output file name, null terminated
;----------------------------------


         .end

测试文件包含以下字符:

 !"#$%&'()*+,-/0123456789:;<=>?@
 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
 abcdefghijklmnopqrstuvwxyz{|}~

它应该只输出:

 ABCDEFGHIJKLMNOPQRSTUVWXYZ 
 ABCDEFGHIJKLMNOPQRSTUVWXYZ

【问题讨论】:

  • 您忘记将String 的字符实际加载到r1 中。您将需要一个循环,因为您一次读取了 128 个字节。当然你应该使用从系统调用返回的数字,因为你可能得到的更少。 PS:学习使用调试器。
  • @Jester 你能解释一下怎么做吗?我正在上课,我们的老师根本没有给我们提供太多关于 ARM 的指令,因为它是一个 x86 汇编课程。
  • 你访问内存中的东西似乎没有问题,你可以做比较和分支,那么你需要解释什么?
  • 这是字符串的加载。我的导师给我们开了一个关于 ARM 组装笔记的笑话,所以很难弄清楚。我们有一个示例程序,它复制整个文件。我在我的基础上使用它并编写了将输出更改为原始帖子中指定的代码。我知道它非常初级,但是我的导师在提供帮助方面有多糟糕(或者缺乏提供帮助更像是它

标签: assembly arm


【解决方案1】:

您的代码有多个问题,您可能应该先制作伪代码或流程图来弄清楚算法。

类似:

while(ReadString(String, 128) != 0)
{
    for(r0 = r1 = String; *r0 != 0; r0++)
    {
        if (IsLower(*r0))
        {
            *r1++ = UpperCase(*r0);
        } else if (IsUpper(*r0) || IsSpace(*r0)) {
            *r1++ = *r0;
        }
    }
    *r0 = 0; /* terminate */
    WriteString(String);
}

现在,将其转换为汇编代码是一件简单的事情。比如:

_read:
     ldr  r0, =InFileHandle   ;r0 points to the input file handle
     ldr  r0, [r0]            ;r0 has the input file handle
     ldr  r1, =String         ;r1 points to the input string
     ldr  r2, =128            ;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

     ldr  r0, =String
     mov  r1, r0
charloop:
     ldrb r2, [r0]
     cmp  r2, #0
     beq  endofstring
     cmp  r2, #'z'
     bgt  skip
     cmp  r2, #'a'
     bge  lower
     cmp  r2, #'Z'
     bgt  skip
     cmp  r2, #'A'
     bge  copy
     cmp  r2, #' '
     beq  copy
     bal  skip
 lower:
     sub  r2, r2, #0x20
 copy:
     strb r2, [r1], #1
 skip:
     add  r0, r0, #1
     bal  charloop
 endofstring:
     strb r2, [r1]            ; copy the terminating zero

     ldr  r0, =OutFileHandle  ;r0 points to the output file handle
     ldr  r0, [r0]            ;r0 has the output file handle
     ldr  r1, =String         ;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         

注意上面代码中的错误,我还没有测试过:)

PS:从上到下的差异是 0x20 而不是 20,而在您的代码中是 0x14。

【讨论】:

  • 非常感谢您的帮助!我绝对看到你所做的与我所拥有的。对理解我的 ARM 任务有很大帮助
猜你喜欢
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2017-10-26
  • 2021-08-13
  • 2018-04-07
相关资源
最近更新 更多