将用户输入的字符串/字符与另一个字符串/字符进行比较

时间:2017-09-23 07:36:41

标签: string assembly arm string-comparison

所以我是ARM Assembly的初学者(一般来说也是程序集)。现在我正在编写一个程序,其中最重要的部分之一是用户需要输入一个字母,然后我会将该字母与其他预先输入的字母进行比较,以查看用户是否输入了相同的字母事情。

例如,在我的代码中我有

.balign 4 /* Forces the next data declaration to be on a 4 byte segment */
dime: .asciz "D\n"

位于文件顶部,

addr_dime               : .word dime

位于文件底部。

另外,根据我在线阅读的内容,我提出了

.balign 4
inputChoice: .asciz "%d"

位于文件顶部,然后输入

inputVal                : .word 0

位于文件底部。

靠近文件的中间位置(只要相信这个独立代码有问题,并且文件的其余部分在此上下文中无关紧要)我有这段代码:

ldr r3, addr_dime
ldr r2, addr_inputChoice
cmp r2, r3                  /*See if the user entered D*/
addeq r5, r5, #10           /*add 10 to the total if so*/

我认为应该将“D”加载到r3中,加载用户输入到r2中的字符串或字符,然后如果它们相同则将10加到r5。

由于某些原因,这不起作用,并且r5,r5,#10代码仅在addne出现之前有效。

1 个答案:

答案 0 :(得分:0)

addr_dime : .word dime无可救药地过于复杂。地址已经是链接时间常量。将地址存储在内存中(在具有自己地址的另一个位置)根本没有帮助,它只是添加了另一层间接。 (这实际上是你问题的根源。)

无论如何,cmp不会取消引用它的寄存器操作数,所以你要比较指针。如果单步使用调试器,您将看到寄存器中的值是指针。

要加载dime的单字节,零扩展到r3,请执行

ldrb r3, dime

使用ldr执行32位加载也会得到\n字节,而32位比较也必须与eq匹配才能成为真。< / p>

但这只能在dime足够接近PC相对寻址模式时才能工作;与大多数RISC机器一样,ARM不能使用任意绝对地址,因为指令宽度是固定的。

对于常量,最简单的避免方法是将其存储在内存中。使用.equ dime, 'D'定义数字常量,然后使用

cmp r2, dime      @ compare with immediate operand

ldr r3, =dime要求汇编程序将常量输入寄存器。您可以使用地址执行此操作,因此您可以执行此操作

ldr   r2, =inputVal     @ r2 = &inputVal
ldrb  r2, [r2]          @ load first byte of inputVal

这是处理静态数据加载的通用方法,这些数据对于PC相对寻址模式来说可能太远了。

您可以使用堆栈地址(sub sp, #16 / mov r5, sp或其他内容)来避免这种情况。然后你已经在寄存器中有了这个地址。

这正是C编译器的作用:

char dime[4] = "D\n";
char input[4] = "xyz";

int foo(int start) {
    if (dime[0] == input[0])
        start += 10;
    return start;
}

来自Godbolt compiler explorer上的ARM32 gcc6.3:

foo:
        ldr     r3, .L4         @ load a pointer to the data section at dime / input
        ldrb    r2, [r3]
        ldrb    r3, [r3, #4]
        cmp     r2, r3
        addeq   r0, r0, #10
        bx      lr
.L4:
        @ gcc greated this "literal pool" next to the code
        @ holding a pointer it can use to access the data section,
        @ wherever the linker ends up putting it.
        .word   .LANCHOR0

.section .data
.p2align  2
 @@@ These are in a different section, near each other.
 @@@ On Godbolt, click the .text button to see full assembler directives.

.LANCHOR0:      @  actually defined with a .set directive, but same difference.
dime:
        .ascii  "D\012\000"
input:
        .ascii  "xyz\000"

尝试更改C以与文字字符进行比较而不是全局编译器无法优化为常量,并看看你得到了什么。

相关问题