2012-05-06 114 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 */ 

这应该让你过去一些你的问题。正如你正在编写汇编,它真的有助于评论它疯狂,与!在每一行之后,以及在你追踪本地变量的顶部的块。大会看起来不那么简单,所以它确实有帮助。