Assembly 汇编(英特尔x86)函数来查找字符串的长度,为什么我会得到额外的字符?
我是汇编初学者,我有一个家庭作业,我必须创建一个Assembly 汇编(英特尔x86)函数来查找字符串的长度,为什么我会得到额外的字符?,assembly,x86,nasm,Assembly,X86,Nasm,我是汇编初学者,我有一个家庭作业,我必须创建一个strlen函数来查找任何字符串的长度 我尝试从edx中减去4,因为我在末尾看到了4个额外的字符,但这并没有解决任何问题。他们还在那里 section .data text: db "Hello world, trying to find length of string using function." ;our string to be outputted section .text global _start ;decla
strlen
函数来查找任何字符串的长度
我尝试从edx中减去4,因为我在末尾看到了4个额外的字符,但这并没有解决任何问题。他们还在那里
section .data
text: db "Hello world, trying to find length of string using function." ;our string to be outputted
section .text
global _start ;declared for linker
_start:
mov eax, 4 ;system call number (sys write)
mov ebx, 1 ;file descriptor to write-only
mov ecx, text ;message to output
call strlen
mov edx, len ;length of string to print
int 80h ;interrupt
exit:
mov eax, 1 ;system call number (sys exit)
mov ebx, 0 ;file descriptor to read-only
int 80h ;interrupt
strlen:
push ebp ;prologue, save base pointer
mov ebp, esp ;copy esp to ebp
push edi ;push edi for use
;body
mov edi, text ;save text to edi, and i think when i do that edi expands? if text = 5 bytes, and edi was originally 4, then edi becomes 5?
sub edi, esp ;subtract edi starting point by the esp starting point to get len. ex: edi = 100, esp = 95
mov [len], edi ;copy value of edi onto len
pop edi ;epilogue, pop edi out of stack
mov esp, ebp ;return esp back to top of stack
pop ebp ;pop ebp back to original
ret ;return address
section .bss
len: resb 4 ;4 byte to integer
假设我在.data
部分有以下代码:
section .data
text: db "Hello world, trying to find length of string using function."
预期的输出应该是“Hello world,尝试使用函数查找字符串长度”。但是我得到的是“Hello world,尝试使用函数查找字符串长度。#####”,其中#
是任意随机字符
这是终端输出:谢谢。在调用strlen之前,您已经加载了
ECX
,其中包含您希望知道其长度的字符串地址。然后直接在函数中使用ECX
。在这个小任务上,您不需要使用prolog/epilog代码
strlen: push ecx
dec ecx
.loop: inc ecx
cmp byte ptr [ecx], 0
jne .loop
sub ecx, [esp]
mov [len], ecx ; Save length
pop ecx
ret
此代码在字符串中运行,直到找到零为止。在这一点上,从找到零的地址中减去起始地址(它位于堆栈上的[esp]
)(它位于ECX
中)。这将产生长度
您可以选择在EDX
寄存器中返回结果,而不是将结果放入内存变量中-下一步即可使用强>
只有确保字符串实际上以零结尾时,此版本的strlen才能工作。只需附加零
section .data
text: db "Hello world, trying to find length of string using function.",0
这是NASM
为了获取存储在该位置的长度,需要len周围的方括号
call strlen
mov edx, [len] ; Length of string to print
int 80h
您没有查看字符串中的字节,而是计算
.data
部分和堆栈之间的距离。如果您想查找strlen函数的堆栈溢出,这里有大量strlen函数的示例,否则请从头开始重新启动strlen
函数,因为您当前的尝试完全走错了方向。您甚至没有在ecx
中使用arg,而是将其硬编码为使用text
@Peter Cordes的字符串。谢谢,这是我的第一个作业(教授只是让我们在.data中查找文本的长度,但没有指定)当我意识到我是在看数据段之间的距离,而不是字节时,我就开始工作了。我现在有这个作为我的,它似乎输出我想要的。请告诉我是否有什么我可以修复的。大多数汇编器不会将终止0添加到使用db“…”声明的字符串中。要处理这个问题,请使用db“…”0来附加终止的0。是的,您只需计算长度的一些随机垃圾大值,而不是在字节上循环,直到找到终止的0
字节为止。(您必须确保数据中有db“foo”,0)。然后
write()`将数据写入一个未映射的页面,并返回-EFAULT
,但已经将有效字节复制到stdout文件描述符。可能字符串后面的字节都是巧合的0
,因此您不会在终端上注意到它们'\0'
以零宽度打印。除了我前面的评论之外:除了计算垃圾外,您还使用len
的绝对地址作为长度,而不是该内存的内容。所以有两个showstopper bug,一个只是语法,另一个是基于明显的基本误解(Sep的回答指出了这一点;我在评论时没有看调用方。)我看到这是一个循环,但我认为当堆栈增加时,内存地址会下降?例如,ECX
的第一个字符可能位于内存地址900
处,它的结尾将位于@Jeemong:取消第一次迭代的inc ECX
。另一种选择是使用jmp
到cmp/jne
循环条件进入循环,以检查第一个字节。i、 e.在do{}while(*++p)方面实施while(*p++){}
代码>
call strlen
mov edx, [len] ; Length of string to print
int 80h