我正在编写一个简单的教程,用于迭代可读和可更改代码的字符串。这是一个正在进行的简单操作系统项目的一部分。我正在记录我在学习装配时遇到的所有困惑,然后以一种可以理解的方式呈现它们,但最简单的方法。我在当前表单中编写的代码显示一个字符,完成的表单将遍历字符串,直到它到达null终止符。我想知道为什么我做以下工作。
mov rsi, message + 2 ;print specific character
然而当我做的时候
mov rsi, message + rbp ;print specific character
我收到错误:无效的操作数类型。 我搜索了stackoverflow(以及其他搜索引擎)并且已经进行了随机尝试以找到偏移运算符以实现第一个工作代码的结果。我认为它是一个加号运算符,或者冒号(:)或者括号([]),不知道如何在这里指示偏移量。
这是工作代码版本,如何将其转换为选择要打印的特定字符的“动态”版本?
global _start
section .data
message: db 'hello world!', 10
section .text
_start:
mov rbp, 1 ;tracks position of character to print
mov rax, 1 ;system call number for "write"
mov rdi, 1 ;first argument, where to write (terminal)
mov rsi, message + 2 ;second argument, print specific character
mov rdx, 1 ;third argument, bytes to write
syscall ;envoke process for the parameters/virtually placed lines
mov rax, 60
syscall
我有一个替代版本获取完整的字符串长度然后系统调用使用字符串长度打印出整个字符串,但是在这个版本中我最终想要演示字符串转换,拆分和比较。
答案 0 :(得分:2)
您需要为寄存器中的值添加常量。对于适合32位的地址(如任何静态地址in a normal non-PIE executable),可以将其用作add
的32位立即数操作数。即。
; rsi contains an offset into the array, e.g. from mov esi, 1
add rsi, message
; add rsi, message + 2 ; you can of course use constant offsets from labels, too
(如果您知道索引在静态对象中,则可以使用add esi, message
并仍然获得有效的64位指针,因为静态对象位于虚拟地址空间的低2GiB中。)
要复制并添加,请使用lea rsi, [rbp + message]
如果您不能使用32位绝对地址,请使用RIP相对LEA获取静态对象的地址,然后单独添加寄存器值。
lea rsi, [rel message]
add rsi, rbp
(使用default rel
使其成为[message]
等寻址模式的默认设置。)