记录memset时出现"分段错误"

5

我几天前开始学习汇编语言,然后开始重新编写所有简单的libc函数,例如strlen、strchr或memset。直到我尝试重新编写memset时,我才遇到问题。

这是C函数的原型:

void *memset(void *s, int c, size_t n);

这是我的汇编代码:

[BITS 32]

global my_memset

my_memset:
    push    ebp
    mov     ebp, esp

    mov     eax, [ebp+8]
    mov     edx, [ebp+12]
    mov     ecx, [ebp+16]

myloop:
    mov     [eax], edx
    add     eax, 1
    loop    myloop

endfunc:
    mov     eax, [ebp+8]
    leave
    ret

这是我用于测试的主要内容

#include <stdio.h>

void *my_memset(void *s, int c, size_t n);

void main(void)
{
  char test[] = "thisisatest";

  printf("%s\n", test);
  my_memset(test, 'b', 5);
  printf("%s\n", test);
}

我对使用寄存器有些迷糊,如果我犯了什么大错误,请告诉我。

[编辑] 主要问题已经解决(没有更多的段错误或错误)。但我还有一个最后的 -小- 问题。我收到的字符串是'bbbbb',而应该是'bbbbbsatest'

谢谢,Ephismen。

2个回答

2
您是否可能将字符串文字用作memset的目标?在这种情况下,[EAX]即*s可能指向只读内存。
编辑:假设test和toto是同一个变量,则应该使用const char * test =,因为字符串文字是只读的。尝试使用char test [] =代替,以创建包含文字副本的数组。
编辑2: 今天我有一个JavaScript问题,所以我无法添加评论。
无论如何,新问题是mov [eax],edx,它存储4个字节(其中一些是0)。以前的存储move [eax],dl一次存储1个字节。
编辑3: @stupid_idiot - 我最初写道edx是2个字节(将其与dx混淆),并在看到您的评论之前进行了修复。老实说! :-)

1
mov [eax],edx 存储4个字节,但是没错。这就是在最后一次迭代后用0终止字符串的方法。我完全没有意识到这一点。使用DL或DH而不是edx应该可以解决问题,但不要改变括号。 - Pyjong
Bo Persson:好的,没问题 :) - Pyjong

1

我想你想要:

mov [eax], dl

这将dl寄存器中的移动到由eax指示的内存地址


在提交代码之前,我尝试过这个方法,但仍然遇到了相同的错误。 - Aymeric
eax 是否包含你认为的内容呢?调试器是你在这里最有用的工具。 - Greg Hewgill
EAX 包含我想要的内容,因为如果我注释掉不工作的那一行,它会返回给我相同的字符串。 - Aymeric
1
我认为你应该使用 mov byte ptr [eax], dl - MByD
@MByD:使用dl寄存器应该是隐含的。只有在移动常量(如0)时才需要使用byte ptr,否则汇编程序将不知道要使内存引用多宽。 - Greg Hewgill
是的,没错,但我认为那不是MByD想要指出的。你如何使用[]括号确实很重要。 - Pyjong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接