Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 汇编(英特尔x86)函数来查找字符串的长度,为什么我会得到额外的字符?_Assembly_X86_Nasm - Fatal编程技术网

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