【问题标题】:zero out memory in assembly汇编中的内存归零
【发布时间】:2016-04-11 20:22:34
【问题描述】:

我先从代码开始:

.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
.equ Stdout,  1            @ Set output target to be Stdout
.equ SWI_Exit, 0x11        @ Stop execution
.global _start
.text

_start:
    ldr r0,=InFileName
    mov r1,#0
    swi SWI_Open
    bcs InFileError
    ldr r1,=InFileHandle
    str r0,[r1]
    mov r8, r0      @ r8 will hold the address of the file handle
ReadLoop:
    mov r0, r8
    ldr r1, =LineArray
    mov r2, #256
    swi SWI_RdStr
    bcs EndReached
    @ r1 now has address of the read line
    mov r9, r1      @ r9 will hold the memory address of the read line
    mov r4, #0      @ r4 = START
    mov r5, #1      @ r5 = END 
    bl PerLineFunc      @ r0/r1 args passed to PerLineFunc
    @ ShuffleWord within PerLineFunc should change the words around, so now we just need to print the new line of words
    mov r0, #Stdout
    mov r1, r9
    swi SWI_PrStr
    ldr r1, =NL
    swi SWI_PrStr
    bal ReadLoop

SWI_RdStr 从给定文件中读取一行并将其存储到内存中,地址位置存储在 r1 中。我的问题是我不知道如何将读入行的内存归零。如果第一行是 20 个字符,下一行是 15 个字符,那么在读取第二行之后,第一行的最后 5 个字符还在内存中。

我在想它会是这样的:

ldr r1, =LineArray
str #0, [r1]

但这会返回语法错误...我只是想在再次运行 ReadLoop 之前重置内存。

编辑:在 OP 中发布答案。 这第一部分需要添加到 ReadLoop 的末尾

mov r0, #0
ldr r1, =LineArray
mov r2, #0
bl EraseMemory  @ r0, r1, and r2 passed into EraseMemory

这里是 EraseMemory 函数

EraseMemory:
    str r0, [r1]
    add r1, r1, #4
    add r2, r2, #1
    cmp r2, #64         @ 256 / 4 = 64
    bxeq lr             @ This loop should run 64 times to erase all 256 bytes of memory that were used
    bal EraseMemory

【问题讨论】:

  • 固定 insn 大小的 RISC 机器在单个指令中没有空间容纳立即操作数和寻址模式 + 位移。即使您不使用位移([r1 + 100] 或任何 ARM 语法),存储指令编码对位也有意义。 (这类事情是降低指令集复杂性的重点)。顺便说一句,尽可能避免重新加载常量。您可以将=NL 加载到不同的注册表中,这样您就不会破坏=LineArray
  • 我不太明白你说的第一部分是什么意思。至于加载到寄存器中,我的印象是这样做是可以的,因为这些是内存中的位置。 =NL=LineArray 是不同的内存位置,因此将其加载到 r1 并不是什么大问题。程序的那部分实际上似乎工作得很好,我只是在使用后无法清除内存
  • 我的意思是你似乎不止一次谈论将=LineArray 加载到r1 中,不是吗?我是说您应该将=LineArray 保存在寄存器中,而不是重新加载它。此外,如果NL 在内存中接近LineArray,您可能会使用add r2, r1, #(NL - LineArray) 或其他东西。请记住,ldr reg, =value 是一个伪操作,它可以变成来自附近常量池的负载,而不是立即数。
  • 第一部分解释了为什么str #0, [r1] 不可编码:str 指令没有空间用于立即数,因为它使用所有空闲位来编码寻址模式和位移。它是 RISC,所以如果没有位移,位就为零,而不是可用于其他东西。

标签: memory assembly arm


【解决方案1】:

您首先需要将立即值写入寄存器:

ldr r1, =LineArray
mov r0, #0
str r0, [r1]

【讨论】:

  • 这只会将地址 [r1] 处内存的前 4 个字节(前 32 位)清零。我需要将用于 =LineArray 的所有内存清零
  • 行的大小是多少?在这种情况下,您需要添加一个循环。
  • 嗯,最大值是 256,在看到你的第一个答案后,我想我必须添加一个循环。我只是希望有一种我不知道的指令有一种更简单的方法。感谢您的帮助
  • stmia [rn], {r0-r3}! 有一种更快的方法,其中 r0-r3 被预置零。然后你可以快速清除一个缓存行或 4*32bits。如果对齐是(原文如此)写入,这可能与 DDR 大小同步。
猜你喜欢
  • 2020-09-20
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 2015-07-01
相关资源
最近更新 更多