从C调用的nasm函数最终会进行分段故障
nasm function called from C ends up segfaulting
我只能使用一个条件跳转指令在数组中找到最小最大值。
在编译和链接下面的两个文件后,我得到了一个Segmentation Fault (core dumped)
,但我不明白为什么会这样。
问题:是什么导致分段错误?
main.cpp
#include <cstdio>
#include <time.h>
using namespace std;
extern "C" void minmax(int n, int * tab, int * max, int * min);
int main(){
const int rozmiar = 100000;
const int liczba_powtorzen = 10000;
int tab[rozmiar] = {1, 3, 3, -65, 3, 123, 4, 32, 342, 22, 11, 32, 44, 12, 324, 43};
tab[rozmiar-1] = -1000;
int min, max;
min = 99999;
max = -99999;
clock_t start, stop;
start = clock();
for(int i=0; i<liczba_powtorzen; i++){
minmax(rozmiar, tab, &max, &min);
}
printf("min = %d max = %dn", min, max);
stop = clock();
printf("n time = %f ( %d cykli)", (stop - start)*1.0/CLOCKS_PER_SEC, (stop - start));
return 0;
}
minmax.asm
global minmax ; required for linker and NASM
section .text ; start of the "CODE segment"
minmax:
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi
mov ecx, [ebp+8] ; array length n
mov esi, [ebp+12] ; array address
mov eax, [ebp+16] ;max
mov edi, [ebp+20] ; min
lp: add eax, [esi] ; fetch an array element
cmp eax, [esi]
jl max ; max<[esi] ->update max
cmp edi, [esi]
jg min ; min>[esi] ->update min
add esi, 4 ; move to another element
loop lp ; loop over all elements
max:
mov eax, esi
ret
min:
mov edi, esi
ret
pop esi ; restore used registers
pop ecx
pop ebp
ret ; return to caller
长故事,短:
您需要在使用ret
之前恢复堆栈。
您的asm实现在许多层面上都是错误的,但您的分段错误的原因是对ret
如何工作的理解不足。
ret
无效使用
ret
不会带你回到最后一个跳转,它读取堆栈顶部的值,并返回到该地址。
跳转到min:
或max:
后,调用ret
,此时应该跳转回循环。
这意味着它将尝试返回到堆栈顶部的地址,这当然不是一个有效的地址;您在输入函数时修改了它。
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi ; note, this is where `ret` will try to go
我不知道你到底想做什么,但是汇编函数写得很差。
试试这个:
push ebp
mov ebp, esp ; set up the EBP
push ecx ; save used registers
push esi
mov ecx, [ebp+8] ; array length n
mov esi, [ebp+12] ; array address
mov eax, 0x80000000
mov edi,[ebp+16]
mov [edi], eax
mov eax, 0x7fffffff
mov edi,[ebp+20]
mov [edi], eax
lp:
mov edi,[ebp+16]
lodsd
cmp [edi], eax
jg short _min_test
mov [edi], eax
_min_test:
mov edi,[ebp+20]
cmp [edi], eax
jl short _loop
mov [edi], eax
_loop:
loop lp
pop esi ; restore used registers
pop ecx
pop ebp
ret ; return to caller
相关文章:
- 分段故障(堆芯转储)矢量
- 数组的指针从不分段故障
- Windows 10-使用gtkmm-3.0库和g++[包括再现]的分段故障
- 分段故障 运行C++代码时出现 SIGSEGV
- 分段故障背包问题
- 分段故障 11,从类函数显示动态 C 字符串
- 面临分段故障 使用 ffmpeg 读取视频时,因为"pFormatCtx-> streams [i]-> codecpar"的地址0x00
- 在C++中,当指向删除和指向不同对象时,分段故障指针
- 分段故障说明
- 分段故障(核心转储)-不知道为什么
- 分段故障线程
- hiredis SET遇到分段故障
- 分段故障,合并排序算法
- 多线程程序中的分段故障和gdb回溯上的不完整信息
- 到达主C++之前分段故障
- 分段故障核心使用 IF流转储
- 使用向量的移动键盘排列(分段故障)
- 在二进制树插入和遍历期间,我得到了分段故障
- 分段故障在类之间返回整数
- C++分段故障BST