用寄存器迭代字符串

时间:2019-05-05 03:41:37

标签: assembly nasm

我试图编写一个遍历字符串并写入每个字符以一次输出一个字符的程序,我试图将寄存器用作迭代器(例如在for循环中)然后索引到字符串中但出现错误“无效的操作数类型”

我将r10设置为0

mov r10, 0

然后在我递增r10之后的代码中,我试图为这样的字符串建立索引,但出现错误

mov rsi, hello_str + r10

当我这样做时,这很好用

mov rsi, hello_str + 1

代码:

global _start
section .text
_start:  mov rsi, hello_str
         mov r10, 0
loop:    mov rax, 1
         mov rdi, 1
         mov rsi, test + r10 
         ; when i do mov rsi, test + 1 it prints 'e' as expected
         ; when i do mov rsi, test it prints 'H' as expected
         mov rdx, 1
         syscall

         inc r10
         cmp rsi + r10, 0x00
         jne loop


section .data
hello_str: db "Hello, World!", 0xA

谢谢

1 个答案:

答案 0 :(得分:1)

要在运行时根据寄存器和静态地址计算指针,可以使用
lea rsi, [hello_str + r10]

(需要一种reg + disp32寻址模式,因此仅在Linux上的非PIE可执行文件中可用,其中静态数据的虚拟地址空间不足2GB。)

或者要迭代,请在循环外使用lea rsi, [rel hello_str],然后使用inc rsi转到下一个字节。 (syscall不会销毁rsi)。或者显然更好,将更长的长度传递给一个write系统调用。


mov rsi, hello_str + 1是在汇编+链接时计算的,因此无法在计算中包括运行时寄存器值。 mov-immediate的源操作数必须是生成时常量。根据寄存器计算内容的指令具有不同的助记符:LEA的语法使用内存操作数语法。

要从内存加载,您希望movzx esi, byte [hello_str + r10]将内存中的一个字节零扩展到RSI。