2012-05-06 3 views
1

Привет, я пытаюсь преобразовать эту функцию C, которую я написал в ассемблерный код (дуга 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 

Я отлаживал программу, и ошибка seg возникает, когда я вызываю функцию strtol. Я не совсем уверен, что я делаю неправильно, я думаю, что правильно передаю параметры, но до сих пор получаю эту ошибку. О, и в моем главном я получил что-то, объявленное как FILE * StdError = stderr, чтобы передать stderr как параметр fprintf.

Любая помощь будет назначена.

+2

Вы пытались сбросить код, сгенерированный компилятором C? –

+0

nvm, я действительно не понимаю, что вы имеете в виду. –

+0

objdump -d yourcbinary должен предоставить вам сборку, созданную компилятором – dbrank0

ответ

1

У вас есть пара различных проблем, происходящих вокруг, но тот, который вы можете исправить довольно легко, будет таким, как вы обращаетесь к errno. У вас не должно быть ветви с именем errno, потому что у вас также есть глобальное var 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 

В этом примере% l0 содержит указатель на егто и% l1 имеет значение при егто после вызова strtol. Тогда вы можете исправить ошибку:

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

    /* if body */ 

endif: 

    /* continued code */ 

Это должно помочь вам преодолеть некоторые из ваших проблем. Когда вы пишете сборку, это действительно помогает комментировать ее как сумасшедшую, и с! после каждой строки и блока вверху, где вы отслеживаете локальные вары. Сборка не так просто смотреть, так что это действительно помогает.

Смежные вопросы