尝试在ARM Assembly中构建阵列

时间:2018-06-28 02:04:42

标签: assembly arm

我正在研究ARM Assembly,正在尝试构建一个数组,但它只会打印我写的最后一个单词,如以下示例所示:

Example

我尝试更改递增索引的方式,但结果相同。有人可以告诉我我做错了吗?还是给我看个例子?

代码是(请原谅我的评论,是葡萄牙语):

id="loginToken".*?value="(.*?)"

1 个答案:

答案 0 :(得分:-1)

  

有人可以告诉我我在做什么错吗?

您未使用调试器:http://idownvotedbecau.se/nodebugging/

在没有调试器的情况下进行汇编编程就像尝试组装被蒙住眼睛的机器人一样。有可能,但是要花费更多的时间(难度增加10到100倍,无需开玩笑),技巧和精力。

我找不到您的“ armsim”实际上是什么,以及它在哪里有一些文档,因此请检查您自己或向SW供应商寻求文档和帮助。但是肯定必须有一些调试器,否则,只需使用不同的工具找到不同的ARM仿真器/仿真器,因为在恶意平台上学习ARM组装几乎没有意义。您将在其他ARM模拟器中学习的机器代码几乎是相同的(尽管诸如svc 0x55之类的平台特定服务可能完全不同,并且汇编器中也可能有某些语法,例如在PC x86世界中,大约有10种不同的语法可用于汇编,如果源不包含它使用的是哪种语法的信息,有时可能会造成混淆。


这是您问题的答案,以下是有关代码的一些说明:

    cmp R5, #3

除非您的平台在执行代码后明确指定值的状态,否则使用未初始化的寄存器是不好的做法。我没有检查您的特定平台,但通常在这类学习模拟器中,寄存器为零,但不能保证,即模拟器的创建者应该将随机值放入其中,以便及早了解人员及其工作原理。实际上。

因此,这确实将R5中的未知值与3进行了比较。

    str     r1, [R4]

除非svc确实修改了寄存器中的值(从输出屏幕上猜测可能不会,但是您应该知道),否则它将存储在地址{{ 1}}符号值(内存地址)R4

因此,在完成第一个[input]循环(称为produto_nome之后,与打印循环(称为Loop相反)……您可能应该考虑混淆器行业的职业,在这里看到一些人才),readloop部分中的内存内容类似于(手动“反汇编”回源代码,但是您应该尝试检入模拟器的调试器,如何查看实际的内存内容,同时查看单个-跳过一条指令):

.data

如您所见,内存中只有最后一个输入作为完整输入(甚至那里您也没有办法知道结束位置),之前的输入会被它覆盖(您可以尝试输入“ aaaaa”,“ bbb”,“ c”,看看结果如何,这还将向您显示换行符或零终止符是否为输入的一部分,如果输入只是纯字符串数据,则结果应为“ cbbaa”。

在汇编器中,芯片中只有物理内存,因此它不会像高级编程语言中的公共变量一样动态增长。

由于有很多选择,您将必须决定如何将字符串数组存储在内存中

  • 最未经压缩的紧凑格式,例如i: .word produto_nome .word produto_nome .word produto_nome produto_nome: .ascii "your last input", "remains of previous longer inputs" .skip <remaining bytes to 100> @ ^ = maybe zeroes, if your platform zeroes .data segment quebra_linha: .ascii "\r\n\r" @ on any decent platform "\n" is enough for newline @ (DOS and Windows are different, but those are obsolete and dead) ,它仅占用12个字节,但是很难访问“随机”索引 i ,因为您必须每次都从头开始搜索整个内容,并计算终止零,直到找到第 i 个字符串的开头(顺便说一句,您不需要在打印循环中进行“随机”访问,因为您可以按顺序打印所有值,因此这种形式是合理的您当前代码的选择,但是对于随机访问应用程序来说会有点慢,但是它将使用更少的内存...决策,决策...通常,这种形式用于命令行参数之类的东西,但是会有额外的数组提供的指针指向每个字符串的开头,因此您可以获得良好的性能和紧凑的内存使用率)
  • 最简单的形式,保留3x100字节,因此每个输入字符串都以“数组+ i * 100”地址开头。
  • 像现在一样具有3x4字节的指针数组,但是您还必须保留空间以将输入存储在其他位置,可能像以前的情况一样再次为3x100字节,并存储指向该空间的指针,而不是固定的"aaaaa\0bbb\0c\0"值。

对于初学者而言,最简单的解决方案是使用N * TAM大内存缓冲区,并直接以produto_nome的形式计算指向字符串的指针。

此外,如果您将array_buffer + i * TAM修改为128而不是100(尝试在汇编中使用,而不是像128这样的“四舍五入”值,则在某些情况下,如100的非四舍五入值处理起来会更加复杂对于计算机...哦,顺便说一句,如果您认为“ 100”是四舍五入而“ 128”不是四舍五入,请尝试以二进制形式查看它们,这就是计算机看到它们的方式...),您可以将TAM乘以通过将其左移7次(即i)来获得lsl R4, R5, #7值。

因此,我将修改代码中的这些移位,然后应像i*128那样保留标签i:之后的内存(如果汇编程序能够计算编译时表达式,否则必须使用.skip TAM*3),并直接读取输入以直接定位到数组内存,而无需额外的.skip 384缓冲区,因此您不需要在{{1之后将128字节的字符串复制到数组缓冲区中}}。

还要检查服务produto_nome到底是做什么的,它是否以零终止该字符串,以及它是否在某个地方返回长度。而且,您可能应该只打印输入的数据长度,而不是整个svc 0x55缓冲区(除非mov r0, #0打印服务确实在零终止符之后终止,但它看起来像普通的TAM服务) ,即它将输出到控制台的完整缓冲区,包括文本用户输入后的垃圾。