2014-12-22 6 views
1

В настоящее время я работаю над простым кодом сборки SPARC, который вычисляет факториал 5. Я хотел бы знать, почему глобальные регистры, которые я использовал, не являются согласованными вызовами функций.Сборка Sparc - глобальные регистры не согласованы во всех функциях вызова

С традиционной французской версией с использованием локальных регистров и параметров вывода/ввода (в% о0), у меня нет никаких проблем, код прекрасно работает,

, но когда я хочу использовать другой вариант с глобальными регистрами, У меня есть проблема непротиворечивости.

Вот код:

.data 
.LLC0: .asciz "fact(5) = %d\n" 

.text 
.global main 

main: 
     save %sp, -96, %sp 

     set 5, %g1    ! value 5 into %g1 register 
     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g1, %o1 
     call printf 
     nop 

     mov %g1, %o0    ! set %g1 into parameter for fact function 
     call fact 
     nop 

     mov %o0, %g4 
     sethi %hi(.LLC0), %g3 
     or %g3, %lo(.LLC0), %o0 
     mov %g4, %o1 
     call printf 
     nop 
     ret 

fact: 
     addcc %g1, -1, %g1  ! current index of the procedure - 
           ! supposed to be decremented at each call - 
     be term     ! PROBLEM : %g1 always set to 0 before decrement 
     nop 

     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g1, %o1 
     call printf    ! printf the value of %g1 : 
           ! still equal to -1 at execution 
     nop 

     call fact 
     nop 
     mov %o0, %g2 
     umul %g2, %g1, %g2 
     mov %g2, %i0 
     ret 

term: set 1, %o0 
     ret 

Моя проблема заключается в том, что, в fact функции, глобальный регистр %g1 устанавливается в 0 при каждом вызове, так что печать %g1 дает всегда -1 при исполнении.

Из этого link я думал, что глобальные регистры являются постоянными во всех вызовах функций, т. Е. Их область действия глобальна и разделена любой функцией в коде.

Например, здесь я поставил set 5, %g1 в основном разделе, и, как правило, я должен получить 4 для напечатанного значения в функции fact.

Если бы кто-нибудь мог понять, что случилось?

Благодаря

UPDATE:

вызов Printf использует% о0 и% o1, а не% g1. У меня все еще есть проблемы с объемом глобальных регистров (% g5-g7). Вот пример их использования, как это:

.data 
.LLC0: .asciz "fact(5) = %d\n" 

.text 
.global main 

main: 
     save %sp, -120, %sp 

     set 5, %g5 
     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g5, %o1 
     call printf 
     nop 

     mov %g5, %o0 
     call fact 
     nop 

     mov %o0, %g7 
     sethi %hi(.LLC0), %g3 
     or %g3, %lo(.LLC0), %o0 
     mov %g7, %o1 
     call printf 
     nop 
     ret 
     restore 

fact: 
     addcc %g5, -1, %g5 
     be term 
     nop 

     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g5, %o1 
     call printf 
     nop 

     call fact 
     nop 
     mov %o0, %g6 
     smul %g6, %g5, %g6 
     mov %g6, %o0 
     ret 

term: set 1, %o0 
     ret 

В этом коде я напечатает значение global %g5 register при каждом рекурсивном вызове и выход:

fact(5) = 5 
fact(5) = 838860799 
fact(5) = 838860798 
fact(5) = 838860797 
fact(5) = 838860796 
fact(5) = 838860795 
fact(5) = 838860794 
fact(5) = 838860793 
fact(5) = 838860792 
fact(5) = 838860791 
fact(5) = 838860790 
... 

кажется, первый вызов факта из основной вывод теряют начальное значение для %g5 (инициализировано до 5)

Где моя ошибка?

Благодаря

ответ

1

С СПАРК ассемблере Справочное руководство (https://docs.oracle.com/cd/E26502_01/html/E28387/toc.html)

6.2 Регистрация Использование

Глобальные регистры% g0-% g7 являются более сложными. Регистр% g0 всегда равен нулю. % g6 и% g7 всегда зарезервированы для операционной системы, поэтому код сборки не должен изменять их.Другие глобальные регистры, % g1-% g5, являются вызывающими, сохраняют и могут использоваться кодом приложения. Но обратите внимание, что% g1 и% g5 могут использоваться в таблице привязки программ (PLT) или другом коде интерполяции и, следовательно, не могут использоваться для передачи параметров от вызывающего абонента до вызываемого абонента.

(курсив мой)

Я думаю, ваша проблема в том, что «В соответствии на протяжении функций называют» означает, что вызов и инструкции по возврату (и др) не влияют на регистры (с окном регистра переключения), но что соглашение о вызове действительно позволяет вызываемому изменять регистры, и, следовательно, содержимое может не пережить вызов.

0

%g1 - %g4 are volatile - ваш вызов printf переопределяет значение, которое вы положили в %g1 раньше, потому что реализация printf «s также использует его.