Assembly 在汇编x86中实现memset

Assembly 在汇编x86中实现memset,assembly,x86,segmentation-fault,Assembly,X86,Segmentation Fault,我正在尝试在程序集x86中实现memset。这两个函数都是按字节和按字复制的,所以我得到了两个函数:kmemset和kmemsetw,我以这种方式向我的C代码公开它们: extern uint8_t* kmemset(uint8_t* dest, uint8_t val, uint8_t size); extern uint16_t* kmemsetw(uint16_t* dest, uint16_t val, uint8_t size); 问题是当我测试它时,我得到了一个分段错误。我

我正在尝试在程序集x86中实现memset。这两个函数都是按字节和按字复制的,所以我得到了两个函数:
kmemset
kmemsetw
,我以这种方式向我的C代码公开它们:

extern uint8_t* kmemset(uint8_t* dest, uint8_t val, uint8_t size);  
extern uint16_t* kmemsetw(uint16_t* dest, uint16_t val, uint8_t size);  
问题是当我测试它时,我得到了一个分段错误。我试图用gdb进行调试,但它似乎无法进入asm代码。如果有人能对代码发表评论,我会很高兴。(
kmemset
非常相似,所以我没有包括它)


您的参数引用位置已关闭4。如果在函数序言中按ebp,然后更新epb,则函数ebp后的前两个(4字节)位置将包含ebp(SFP)和ret。您的代码使ret成为字符串副本的目标位置。在所有引用中添加4。

在如何传递/引用参数方面也可能存在问题,但从代码片段中还不清楚这一点


编辑:这不是您的错误,但您还需要更改返回方式。edi在rep存储期间更新,因此要返回指向内存区域开头的指针,请从存储它的ebx获取它

您的过程中没有使用
ebx
,为什么要保存它?它不需要保存
ecx
是一个易失性寄存器,您不需要保存它

正如前面提到的规则,进程中的参数是关闭的

另一个大问题是,您不需要在最后恢复堆栈指针。当然你要弹出ebp,但是你在哪里呢???您可以在开始时
mov ebp,esp
,但决不能将其反转

如果查看
memset
,它将返回传递给进程的指针。因此,这是错误的:
mov-eax,edi
应该是:
mov-eax,[ebp+8]
rep stos?
递增
edi
中的指针,因此如果返回
edi
,则返回的指针是错误的

但是为什么还要为这个小程序设置堆栈框架呢?只需使用
esp
,因为我们需要将
edi
保存到堆栈中,因此
esp
中的参数偏移量将与设置堆栈帧时的偏移量相同:

kmemset:      
    push    edi             ; proc uses edi, so save it.

    mov     ecx, [esp + 16] ; size_t num
    mov     al, [esp + 12]  ; int value 
    mov     edi, [esp + 8]  ; void * ptr
    rep     stosb 

    mov     eax, [esp + 8]  ; return pointer
    pop     edi             ; restore edi
    ret                     ; let caller adjust stack
使用
stosw
会有点不同

SomeProc:
    push    ebp
    mov     ebp, esp
    push    edi

    ; params are at:
     ;~ ebp + 8
     ;~ ebp + 12
     ;~ ebp + 16
     etc...
    ; ...
    ; ...
    ; ...

    pop     edi
    ; the following 2 lines
    ; can be replaced with
    ; leave
    mov     esp, ebp
    pop     ebp
    ret

长度参数是以字节还是以字为单位接收的?另外还有
stosd
(dword大小的存储)。谢谢您的提示。另外,length参数作为字节(uint8_t)传递,但现在将其更改为双字(uint32_t)。您好,非常感谢。事实上,我的代码中有两个主要错误,ret地址缺少4字节的偏移量,加上esp寄存器的重置。感谢函数模板,让事情变得清晰。(同时也感谢gnome的第一个提示,感谢nrz的编辑)如果您突然从[di]开始倒退,您可能也想做一个CLD!
SomeProc:
    push    ebp
    mov     ebp, esp
    push    edi

    ; params are at:
     ;~ ebp + 8
     ;~ ebp + 12
     ;~ ebp + 16
     etc...
    ; ...
    ; ...
    ; ...

    pop     edi
    ; the following 2 lines
    ; can be replaced with
    ; leave
    mov     esp, ebp
    pop     ebp
    ret