程序集调用c函数并存储计数器,不在寄存器中

时间:2013-05-08 08:47:00

标签: assembly

我正在完成一个汇编程序,用一个给定的替换字符替换字符串中的字符。汇编代码调用C函数,汇编程序本身在我的.c文件中从main调用。但是,我试图找到一个适当的寄存器来存储某种计数器来计算一个字符被替换的次数。最终我会在返回调用c函数之前将该值放入eax(在这种情况下会将该值返回给r)。

编辑:修复!我意识到我不需要实际存储我在ebx寄存器中通过程序集调用的c函数的返回值。这释放bl用作计数器,然后我将al分配给bl。由于al是16位版本的eax,我可以返回eax,它将包含更改的字符数!

我的[修复]汇编代码是:

 ; File: strrepl.asm
; Implements a C function with the prototype:
;
;   int strrepl(char *str, int c, int (* isinsubset) (int c) ) ;
;
; 
; Result: chars in string are replaced with the replacement character and string is returned.

    SECTION .text
    global  strrepl


_strrepl:   nop
strrepl:
    push    ebp         ; set up stack frame
    mov ebp, esp

    push    esi         ; save registers
    push    ebx
    xor eax, eax
    mov ecx, [ebp + 8]      ;load string (char array) into ecx
    jecxz   end         ;jump if [ecx] is zero
    mov al, [ebp + 12]      ;move the replacement character into esi
    mov edx, [ebp + 16]     ;move function pointer into edx
    xor bl, bl
firstLoop:

    xor eax, eax

    mov edi, [ecx]
    cmp edi, 0
    jz  end

    mov edi, ecx        ; save array

    movzx   eax, byte [ecx]     ;load single byte into eax  
    push    eax         ; parameter for (*isinsubset)
    mov edx, [ebp + 16]         
    call    edx         ; execute (*isinsubset)

    mov ecx, edi        ; restore array
    cmp eax, 0
    jne secondLoop  
    add esp, 4          ; "pop off" the parameter
    add ecx, 1
    jmp firstLoop

secondLoop:
    mov eax, [ebp+12]
    mov [ecx], al
    inc bl
    mov edx, [ebp+16]
    add esp, 4
    add ecx, 1
    jmp     firstLoop

end:
    xor eax, eax
    mov al, bl
    pop ebx         ; restore registers
    pop esi
    mov esp, ebp        ; take down stack frame
    pop ebp
    ret

1 个答案:

答案 0 :(得分:1)

这里还有一些问题: -

  1. 确保您没有损坏需要保留的寄存器!在Win32上,必须保留以下内容:edi,esi,ebp和ebx(您正在废弃edi)。其他操作系统可能需要保留不同的寄存器。

  2. 您调用的函数也是如此,因此您调用的函数必须保留这些寄存器,但可以自由更改其余的寄存器。

  3. 您正在对字符串的结尾进行双字检查,应该是字节检查。

  4. 寄存器用法 - 每个寄存器都有一个定义的使用模式,一些指令使用隐式寄存器(例如loop,mul等)

  5. 您的评论错误。返回是替换字符的数量,而不是输入字符串,除非代码错误且注释正确。

  6. 以下是我如何实现这一点,用VS2010编写并使用MS特定的内联汇编格式: -

    int __declspec (naked) my_strrepl (char *string, int c, int (*isinsubset) (int c))
    {
      __asm
      {
        push ebp
        mov ebp, esp
        push esi
        push ebx
    
        xor ebx,ebx
        mov esi,string
        or esi,esi
        jz null_string
    
    check_loop:
        lodsb
        and eax,0xff
        jz null_string
        push eax
        mov edx,isinsubset
        call edx
        add sp,4
        or eax,eax
        jz check_loop
        inc ebx
        mov eax,c
        mov [esi-1],al
        jmp check_loop
    
    null_string:
        mov eax,ebx
        pop ebx
        pop esi
        mov esp,ebp
        pop ebp
        ret
      }
    }