我目前正在嘗試將匯編函式鏈接到我的 C 代碼驅動程式以進行大學作業。執行程式后,出現段錯誤錯誤。
下面將包括我的 C 檔案、ASM 檔案中的內容以及來自 GDB 除錯器的資訊。
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void add(char*, char*); //would extern be needed here maybe?
int main(){
int choice;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do{
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5){
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
}
switch(choice){
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
fgets(num1, 1024, stdin);
num1[strlen(num1) - 1] = '\0';
printf("\nPlease enter a second number: ");
fgets(num2, 1024, stdin);
num2[strlen(num2) - 1] = '\0';
add(num1, num2);
printf("\nResult: %s\n", num2);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
}
}while(choice != 5);
return 0;
}
這里要注意的一件事是,我的教授特別指出我將兩個數字作為字串讀入,然后atoi()在匯編中使用該函式將字串轉換為 int。
現在,我的 ASM 代碼:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push eax
call atoi
push ebx
call atoi
mov eax, [ebp 8]
mov ebx, [ebp 12]
add eax, ebx
pop ebx
ret
由于我需要atoi()從我的程式集函式呼叫,我認為有必要使用堆疊。
最后,GDB 除錯器說的是:
Program received signal SIGSEGV, Segmentation fault. 0xffffcdbc in ?? ()
關于除錯器錯誤的說明:當單步執行程式時,它會在到達add(num1, num2).
對于其他一些重要資訊,我使用 GCC 編譯器、NASM 編譯器、Intel Assembler i386,并通過 VirtualBox 在虛擬機中運行 Debian 10 x86_64。
對此事的任何幫助將不勝感激!
uj5u.com熱心網友回復:
我看到的第一個問題是你使用的:
fgets(num1, 1024, stdin); 但是 num1 只有 3 個位元組作為緩沖區,但這并不是分段錯誤的根本原因。
另一個問題是您將add函式宣告為:
void add(char*, char*);. 我認為將其宣告為int add(char*, char*);并將此函式的結果用作兩個數字的總和更容易。
問題出在匯編代碼中,您沒有使用正確的引數。例如在這部分:
push eax
call atoi
push ebx
call atoi
您使用eax和ebx作為 的引數atoi,但add函式的引數在[ebp 8]和 中[ebp 12]。呼叫之后你需要確保堆疊是干凈的并且你需要使用add esp, 4(因為它只有一個引數)
要記住的另一件事是 aftercall atoi結果將存盤在eax暫存器中,因為您呼叫atoiafteratoi將丟失第一個結果。您需要存盤第一個atoi(在堆疊/區域變數上)的結果,然后將其添加到第二次呼叫的下一個結果中atoi。我將把我的 C 代碼和程式集版本放在 32 位上。
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(char*, char*); //would extern be needed here maybe?
int main(){
int choice;
int sum;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do{
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5){
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
}
switch(choice){
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
scanf("%s", num1);
printf("\nPlease enter a second number: ");
scanf("%s", num2);
sum = add(num1, num2);
printf("\nResult: %d\n", sum);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
}
}while(choice != 5);
return 0;
}
匯編代碼:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push dword [ebp 8]
call atoi
add esp, 4
push eax
push dword [ebp 12]
call atoi
add esp, 4
pop ecx
add eax, ecx
leave
ret
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/369164.html
