[英]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.