我正在完成一个汇编程序,用一个给定的替换字符替换字符串中的字符。汇编代码调用C函数,汇编程序本身在我的.c文件中从main调用。但是,当尝试完成并从汇编程序TO 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。这只是一个测试,看看我是否可以将一个int返回到c文件中的r。最终我将返回被替换为r的字符数。但是,我需要弄清楚为什么上面的代码是segfaulting。有任何想法吗?
答案 0 :(得分:1)
mov eax, 9
push eax ; NOT a good idea
ret
这是大错误。它将根据堆栈中最低的东西返回,并且您只是将某些内容推送到堆栈,这几乎肯定不是有效的返回地址。
大多数函数只需将代码放入eax
(这取决于调用约定当然但这是一个非常常见的函数)来返回代码,通常没有必要将它推入堆栈,当然还有很多这样做的缺点。
答案 1 :(得分:0)
返回值通常存储在X86 32位计算机上的EAX中。因此,在将其存储在EAX中之后将其推入堆栈是错误的,因为它返回的函数将尝试使用EAX中的内容作为IP(指令指针)的值
Ret没有参数弹出堆栈的返回地址并跳转到它。