2013-02-15 106 views
1

我有一個彙編語言的例程,可以將字符串轉換爲整數。但是,我怎麼能返回失敗? (例如,在字符串中看到一個非數字),它會將整數值返回到eax,非零值通常不是一個好主意,爲什麼我不能將"0"從錯誤轉換爲0。也許stc在失敗的情況下?你如何實現它?從例程返回失敗

回答

1

如果這是在裝配中,被裝配調用,你有各種選擇。

您可以在%eax(%ebx,%ecx,無論 - 只是做出一個錯誤代碼)的返回值中返回一個錯誤代碼(0代表沒有錯誤,1代表錯誤,或者錯誤發生的字符串中的偏移量)確保調用者在調用你的函數之前保存該寄存器)。

您可以在%eflags中設置一個標誌,如奇偶校驗(PF)。 RET指令不會修改任何標誌,因此清除標誌並將其設置爲退出將意味着標誌在您的例程返回時仍然置位。請確保選擇一個在您清除並設置它之間不會修改的標誌!

您可以觸發一個異常(例如溢出)並讓調用者捕獲它 - 但這對於字符串轉換等操作有點過分。如果未正確捕獲異常,您可能會使調用應用程序崩潰。

如果您希望彙編語言例程像庫函數那樣被調用(即通過未指定的編程語言中已建立的調用約定調用),那麼您確實有以下兩種選擇之一:使用全局函數或調用者傳入一個你的例程可以用來寫入錯誤代碼的指針。看看strtoul(3)是如何做到的。

1

這取決於你的功能是否需要遵循傳統的調用約定。如果它可以被你沒有組裝級別控制的功能調用,例如C函數,那麼你不能使用進位位來指示錯誤,因爲沒有辦法告訴編譯器檢查它。如果你的代碼將在很多地方使用,那麼最好遵循調用約定,因爲它們都需要知道它是如何返回值的。

如果你的函數只被彙編代碼使用,那麼你可以根據需要返回一個錯誤。設置進位標誌(stc)是常用選擇。例如,BIOS功能使用它,我個人曾經使用它。請確保成功清除進位標誌(clc)。

另一種可能性是使用兩個寄存器作爲返回值,一個用於實際結果,另一個用於錯誤代碼。如果使用edx,這實際上與某些編譯器(如gcc)兼容,後者使用edx:eax作爲64位整數或適合64位的結構的結果位置。最後,如果您需要確保與所有編譯器的兼容性,您應該讓函數接受一個額外的參數,該參數是指向實際結果的指針,並且僅返回一個錯誤代碼。在C中,這看起來像這樣:

int myFunction(int otherArguments, int *resultPointer) { 
    int errorCode, result; 
    ... 
    *resultPointer = result; 
    return errorCode; 
} 
1

簡而言之,您將返回一個額外的值。

選項之一(C),使用全局變量:

#include <stdio.h> 

int error = 0; 

int String2Int(const char* s) 
{ 
    ... 
    if (some_error_condition) 
    error = 1; 
    ... 
} 

int main(void) 
{ 
    int value; 
    error = 0; 
    value = String2Int("12g"); 
    if (error != 0) 
    printf("error!\n"); 
    return 0; 
} 

選擇二,一個指針傳遞給錯誤變量:

#include <stdio.h> 

int String2Int(const char* s, int* error) 
{ 
    ... 
    if (some_error_condition) 
    *error = 1; 
    ... 
} 

int main(void) 
{ 
    int error = 0; 
    int value = String2Int("12g", &error); 
    if (error != 0) 
    printf("error!\n"); 
    return 0; 
} 

選項樹,返回的結構:

#include <stdio.h> 

struct valerr 
{ 
    int value; 
    int error; 
}; 

struct valerr String2Int(const char* s) 
{ 
    struct valerr ve; 
    ... 
    if (some_error_condition) 
    ve.error = 1; 
    ... 
    return ve; 
} 

int main(void) 
{ 
    struct valerr ve = String2Int("12g"); 
    if (ve.error != 0) 
    printf("error!\n"); 
    return 0; 
} 

在後一種情況下,編譯器可能將一個隱式參數插入到String2Int(),指向ve,以便return ve;知道在哪裏存儲返回的結構。