2012-05-06 148 views
1

嗨,我試圖轉換此函數,我寫入彙編代碼(SPARC弧),但不斷收到分段錯誤(核心轉儲)錯誤。該函數應該將字符串轉換爲長整型值。我知道我正確地完成了C函數,因爲我測試了它並且它通過了所有的測試。這是我試圖轉換的C函數。將C函數轉換爲程序集

long strToLong(char *str, int base) 
{ 
    char *endptr; 
    errno = 0; 
    long num; 
    num = strtol(str, &endptr, base); 
    char holder[BUFSIZ]; 

    /*if *endptr isn't '\0' then strtol didn't get to the end of the string 
    *so it wasn't a valid integer*/ 
    if(*endptr != '\0') 
    { 
    (void)fprintf(stderr, "\n\t""'%s'" " is not an integer\n", str); 
    return 0; 
    } 
    /*if errno isn't 0 then an error occured so print out an error message*/ 
    else if(errno != 0) 
    { 
    (void)snprintf(holder, BUFSIZ,"\n\tConverting \"%s\" base \"%d\"\n caused an   ", str, base); 
    perror(holder); 
    return 0; 
    } 

    /*if no errors, then it was a valid integer so return the integer*/ 
    return num; 
} 

這是我寫的彙編代碼。

.global strToULong 

.section ".data"  

fmt1: .asciz "%s is not an integer\n" !ascii format 

fmt2: 
    .asciz "Converting %s base %d\n" !ascii format 

.section ".text" 

strToULong: 
    save %sp, -(92 + 1028) & -8, %sp 
    add %fp, -4, %o1 
    mov %i0, %o0 
    mov %i2, %o2 
    call strtol 
    nop 
    mov %o0, %l0 
    ld [%fp - 4], %l1 
    ldub [%l1], %l1 
    cmp %l1, %g0 
    be errno 
    nop 

    set stdError, %o0 
    ld [%o0], %o0 
    set fmt1, %o1 
    mov %i0, %o2 
    call fprintf, 3 
    nop 

errno: 
    mov %l0, %i0 
    set errno, %l2 
    ld [%l2], %l2 
    cmp %l2, %g0 
    be return 
    nop 

    add %fp, -1028, %o0 
    mov 1024, %o1 
    set fmt2, %o2 
    mov %i0, %o3 
    mov %i1, %o4 
    call snprintf 
    nop 
    add %fp, -1028, %o0 
    call perror 
    nop 
    mov 0, %i0 

return: 
    ret 
    restore 

我調試了程序,當我調用strtol函數時出現seg錯誤。林不知道我做錯了什麼,我想我正確地傳遞參數,但我仍然得到這個錯誤。哦,在我的主要我有一些聲明像FILE * StdError = stderr將stderr作爲參數傳遞給fprintf。

任何幫助將appriciated。

+2

您是否嘗試轉儲由C編譯器生成的代碼? –

+0

nvm,我其實不太明白你的意思。 –

+0

objdump -d yourcbinary應該給你編譯器生成的程序集 – dbrank0

回答

1

你周圍有幾個不同的問題,但你可以很容易地修復的問題就是你訪問errno的方式。你不應該有一個名爲errno的分支,因爲你也有一個全局變量errno,這可能會導致一些混淆。

由於errno將是一個全局變量,加載錯誤號到寄存器應該是這樣的:

set errno, %l0 !sets %o0 to a pointer to errno 
    st %g0,[%l0]  !set errno to 0 

    set %i0, %o0  !move str to output 
    set endptr, %01 !move endptr to output (defined above in .section ".data") 
    set %i1, %o2  !move base to output 

    call strtol,2  !calls strtol with given inputs 
    nop 

    ld [%l0], %l1 !loads the value at errno into %l1 

在這個例子中,%10具有指向錯誤號和%L1調用後,在錯誤號持有的價值與strtol。然後你可以錯誤檢查:

cmp %l1,%g0  !compares errno to 0 
    be endif 
    nop 

    /* if body */ 

endif: 

    /* continued code */ 

這應該讓你過去一些你的問題。正如你正在編寫彙編,它真的有助於評論它瘋狂,與!在每一行之後,以及在你追蹤本地變量的頂部的塊。大會看起來不那麼簡單,所以它確實有幫助。