繁体   English   中英

汇编返回int到C函数段

[英]Assembly Return int to C function segfaults

我正在完成一个汇编程序,该程序用给定的替换字符替换字符串中的字符。 汇编代码调用C函数,而汇编程序本身是从我的.c文件中的main调用的。 但是,当尝试完成并从汇编程序向C返回最终的int值时,我遇到了段错误。 我的.asm文件如下:

; 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

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
    mov ebx, eax        ; store return value
    add ecx, 1
    jmp firstLoop

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

end:
    pop ebx         ; restore registers
    pop esi
    mov esp, ebp        ; take down stack frame
    pop ebp
    mov eax, 9
    push    eax         ;test
    ret

我的C文件是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//display *((char *) $edi)
// These functions will be implemented in assembly:
//

int strrepl(char *str, int c, int (* isinsubset) (int c) ) ;


int isvowel (int c) {

   if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') 
      return 1 ;

   if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') 
      return 1 ;

   return 0 ;
}

int main(){
    char *str1;
    int r;


    str1 = strdup("ABC 123 779 Hello World") ;
    r = strrepl(str1, '#', &isdigit) ;
    printf("str1 = \"%s\"\n", str1) ;
    printf("%d chararcters were replaced\n", r) ;
    free(str1) ;
    return 0;
}

在我的汇编代码中,您可以看到最后

mov eax, 9
push    eax 

我只是试图将值9返回到值“ r”,这是C文件中的一个int值。 这只是一个测试,看是否可以在c文件中将int返回给r。 最终,我将返回的字符数返回给r。 但是,我需要弄清楚为什么上面的以下代码是段错误的。 有任何想法吗?

mov     eax, 9
push    eax          ; NOT a good idea
ret

那是个错误。 它会根据堆栈中最低的内容返回,而您只是将肯定不是有效的返回地址的内容压入堆栈。

大多数函数只是通过将其放入eax返回代码(这当然取决于调用约定,但这是很常见的一种),通常不需要将其压入堆栈,并且这样做的缺点也很多。

返回值通常存储在X86 32位计算机上的EAX中。 因此,将其存储在EAX中之后将其推入堆栈是错误的,因为返回的函数将尝试使用EAX中的内容作为IP(指令指针)的值

没有参数的Ret将返回地址弹出堆栈,并跳转到该地址。

资源

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM