[英]C printf Segmentation fault (core dumped) while mixing with Assembly code
我嘗試了一些混合C代碼和x86匯編代碼的基本示例。 這是簡單的查找較小數字的示例。
這是bs文件中的匯編代碼(我必須使用無前綴和i386體系結構的intel語法):
.intel_syntax noprefix
.arch i386
.data
.globl out_format
out_format:
.asciz "min(%i, %i) = %i\n"
.text
.globl min
.type min, @function
min:
enter 0, 0
mov ebx, [ebp + 8]
cmp ebx, [ebp + 12]
jle 1f
mov eax, [ebp] + 12
jmp 2f
1:
mov eax, ebx
2:
leave
ret 8
.end
這是ac文件中的C代碼:
#include<stdio.h>
extern char out_format;
extern int min(int x, int y);
int main() {
int x1, x2, r;
scanf("%i%i", &x1, &x2);
r = min(x1, x2);
printf(&out_format, x1, x2, r);
return 0;
}
我在x64 Arch Linux上用gcc編譯它:
gcc -m32 -Wall -Werror -g -o p b.s a.c
但是,當我啟動可執行文件p並插入2個數字並按Enter時,我得到:
Segmentation fault (core dumped)
我研究了所有以前類似的問題,並且嘗試了幾次嘗試,但是每次遇到相同的錯誤時,我都會嘗試。 我也嘗試使用gdb調試它,並且我看到Assembly函數min返回正確的結果,但是無論如何它總是卡在C printf函數上。
我試圖不從匯編文件中導入字符串out_format ,而是直接在C文件中定義它(我將其定義為簡單的char數組,還使用malloc和free函數將其定義為char指針),但沒有幫助。
否則,如果我使用一些整數而不是匯編函數min的結果來初始化變量r ,則程序不會給出此類錯誤。 但這對我沒有任何意義,因為我已經用gdb檢查了它,並且Assembly函數正確地將變量r正確地初始化為正確的較小數字。
拜托,有人可以幫我嗎?
提前致謝
如果min()運作良好,請檢查out_format。
以下代碼有效。
printf("%d %d %d\n", x1, x2, r);
完整的代碼
#include<stdio.h>
int min(int x, int y)
{
if (x<y) return x;
return y;
}
int main() {
int x1, x2, r;
scanf("%i%i", &x1, &x2);
r = min(x1, x2);
printf("%d %d %d\n", x1, x2, r);
return 0;
}
最后,我只想保留有效的代碼。
文件bs:
.intel_syntax noprefix
.arch i386
.data
.globl out_format
out_format:
.asciz "min(%i, %i) = %i\n"
.text
.globl min
.type min, @function
min:
enter 0, 0
push ebx
mov ebx, [ebp + 8]
cmp ebx, [ebp + 12]
jle 1f
mov eax, [ebp] + 12
jmp 2f
1:
mov eax, ebx
2:
pop ebx
leave
ret 8
.end
文件ac:
#include<stdio.h>
extern char out_format;
extern int __attribute__((stdcall)) min(int x, int y);
int main() {
int x1, x2, r;
scanf("%i%i", &x1, &x2);
r = min(x1, x2);
printf(&out_format, x1, x2, r);
return 0;
}
感謝大家的幫助。
asm使用ret 8
在返回時從堆棧中彈出args。
標准的32位x86 Linux調用約定( i386 System V ABI )是caller-pops。 函數僅使用ret
返回 ,如果/需要,調用者可以清理堆棧。 (例如,使用mov
存儲在另一個call
之前編寫新的arg,而不是調整esp
並再次使用push
。)
正如OP的自我回答指出的那樣,您可以改為將min
聲明為
extern int __attribute__((stdcall)) min(int x, int y);
因此,編譯器生成的代碼將與調用約定上的asm一致。 該調用約定有時在Windows上使用。
如果與調試器一起進行單步調試,就會發現這一點(如果您知道要查找的內容)。 始終使用調試器找出您的代碼段在哪里,然后查看寄存器並向后工作以找出原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.