Сборка SPARC, установка флага C

Это оставляет меня сбитым с толку, и я действительно не могу понять, почему у меня возникает эта проблема. Я должен создать программу на c, которая выводит беззнаковое значение непосредственно перед установкой флага C, используя ассемблер для накопления переменной с помощью addcc и отправки значения обратно в main в c. Я считаю, что код, который у меня есть для c, правильный:

unsigned int func();

int main(void){
    printf("The max value before the C flag is set is: %u\n", func());
}

Теперь проблема со сборкой...

.global func
func: save %sp, -128, %sp
addcc %g0, 1, %g0
clr %l0

loop:
bcs away
mov %l0, %i0
addcc %i0, 1, %l0
ba loop
nop

away:
ret
restore

Что это должно делать, так это накапливать %l0, когда установлен флаг C, передавая значение обратно в %i0 и возвращая его. Когда я запускаю это, я получаю 0. Это имеет смысл для меня, так как я считаю, что должен получить гораздо большее число. Любая помощь будет оценена по достоинству.


person Dillon Burton    schedule 02.04.2013    source источник
comment
Флаг C указывает на перенос? Тогда я предполагаю, что он настроен на увеличение, когда значение равно UINT_MAX. Теперь UINT_MAX + 1 равно 0.   -  person Daniel Fischer    schedule 03.04.2013
comment
Это именно то, что я предполагал, единственная проблема в том, что я понятия не имею, как я могу вернуть номер до его сброса. Я могу использовать: bcs (ветвь, когда установлен флаг c) или bcc (ветвь, когда флаг c очищен)   -  person Dillon Burton    schedule 03.04.2013
comment
Уменьшите значение на единицу после установки флага (или это обман?).   -  person Daniel Fischer    schedule 03.04.2013
comment
субкопия? Я пробовал, получаю -1.   -  person Dillon Burton    schedule 03.04.2013
comment
Нет, я не думаю, что это будет считаться изменой. Я на мгновение подумал, что по какой-то причине он не зацикливается, отлажен, и да, он зацикливается, поэтому он должен сбрасываться. Однако вычитание единицы приводит к -1! Раздражающий!   -  person Dillon Burton    schedule 03.04.2013
comment
Но вы возвращаетесь и печатаете unsigned int в C, так что это не может быть -1 (ну, битовый шаблон UINT_MAX обычно такой же, как у int -1).   -  person Daniel Fischer    schedule 03.04.2013


Ответы (1)


Проблема в том, что ветки в Sparc задерживаются — следующая за веткой инструкция будет выполнена до фактического выполнения ветки. Итак, когда у вас есть:

bcs away
mov %l0, %i0

когда флаг C установлен и эта ветвь выбрана, mov все еще будет выполняться, перезаписывая значение в %i0 (значение перед последним добавлением, которое устанавливает C) на %l0 (значение после добавления -- 0).

Если вы вставите nop здесь:

bcs away
nop
mov %l0, %i0

это должно дать вам значение, которое вы хотите.

person Chris Dodd    schedule 02.04.2013
comment
Классно сработало! Это никогда не приходило мне в голову, но это имеет смысл. Просто некоторое уточнение, в c, будет ли это правильным способом печати числа без знака? - person Dillon Burton; 03.04.2013
comment
Могу я прокомментировать Что за слово из четырех букв? - person Daniel Fischer; 03.04.2013
comment
@DillonBurton: Да, %u печатает unsigned int - person Chris Dodd; 03.04.2013
comment
@DanielFischer: Слоты задержки ветвления — распространенная ошибка в ранних проектах RISC. - person Chris Dodd; 03.04.2013
comment
@Chris Dodd: Или просто используйте bcs,a away, чтобы аннулировать слот задержки (не выполнять его, если ветвь взята), stackoverflow.com/questions/604119/ - person FrankH.; 03.04.2013
comment
@ Крис Спасибо. Удивительно, но идея имеет смысл. - person Daniel Fischer; 03.04.2013
comment
@FrankH.: за исключением того, что флаг отмены имеет обратный смысл - он пропускает инструкцию, если ветвь не выбрана, что является обратным тому, что вы хотите (и вызовет здесь бесконечный цикл). Вы можете изменить код, чтобы сделать слоты задержки ветвления полезными или сделать аннулированные слоты полезными, но это не относится к делу. - person Chris Dodd; 04.04.2013