如何使用 NASM 查找字符串的长度?
我正在尝试使用 NASM 编写一个程序,该程序从命令行参数获取输入。由于未提供字符串长度,我正在尝试创建一个函数来计算我自己的字符串长度。这是我的尝试,它获取指向 ebx 寄存器中字符串的指针,并返回 ecx 中字符串的长度:
len:
push ebx
mov ecx,0
dec ebx
count:
inc ecx
inc ebx
cmp ebx,0
jnz count
dec ecx
pop ebx
ret
我的方法是遍历字符串,逐个字符,检查是否为空。如果不是,我会增加 ecx 并转到下一个字符。我相信问题在于 cmp ebx,0
对于我想要做的事情来说是不正确的。我将如何正确地检查该字符是否为空?另外,还有其他我可以做得更好的事情吗?
I'm trying to make a program using NASM that takes input from command line arguments. Since string length is not provided, I'm trying to make a function to compute my own. Here is my attempt, which takes a pointer to a string in the ebx
register, and returns the length of the string in ecx
:
len:
push ebx
mov ecx,0
dec ebx
count:
inc ecx
inc ebx
cmp ebx,0
jnz count
dec ecx
pop ebx
ret
My method is to go through the string, character by character, and check if it's null. If it's not, I increment ecx
and go to the next character. I believe the problem is that cmp ebx,0
is incorrect for what I'm trying to do. How would I properly go about checking whether the character is null? Also, are there other things that I could be doing better?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正在将 ebx 中的值与 0 进行比较,这不是您想要的。 ebx 中的值是内存中字符的地址,因此应该像这样取消引用:
此外,最后一个push ebx 应该是pop ebx >。
You are comparing the value in
ebx
with 0 which is not what you want. The value inebx
is the address of a character in memory so it should be dereferenced like this:Also, the last
push ebx
should bepop ebx
.以下是我在检查
argv[1]
的 64 位 Linux 可执行文件中执行此操作的方法。内核使用堆栈上的argc
和argv[]
启动一个新进程,如 x86-64 System V ABI 中所述。这是缓慢且低效的,但很容易理解。
为了提高效率,您只需要
movzx
加载而不是合并到之前的 RAX 中来避免错误的依赖关系价值(为什么 GCC 不使用部分寄存器?)。当然,SSE2 在 x86-64 中始终可用,因此我们应该使用它来检查 16 字节的块(在达到对齐边界后)。查看优化的手写
strlen
实现,例如 glibc 中的实现。 (https://code.woboq.org/userspace/glibc /sysdeps/x86_64/strlen.S.html)。Here is how I do it in a 64-bit Linux executable that checks
argv[1]
. The kernel starts a new process withargc
andargv[]
on the stack, as documented in the x86-64 System V ABI.This is slow and inefficient, but easy to understand.
For efficiency, you'd want
movzx
instead of merging into the previous RAX value (Why doesn't GCC use partial registers?).And of course SSE2 is always available in x86-64, so we should use that to check in chunks of 16 bytes (after reaching an alignment boundary). See optimized hand-written
strlen
implementations like in glibc. (https://code.woboq.org/userspace/glibc/sysdeps/x86_64/strlen.S.html).这是我如何编码的
(结果在 eax 中)。可能有更好的方法。
Here how I would have coded it
(The result is in eax). Likely there are better ways.