Когда должен быть установлен флаг на ассемблере - PullRequest
8 голосов
/ 18 мая 2010

Я озадачен этой проблемой при написании симулятора сборки ARM на C. Я нашел несколько похожих вопросов на форуме, но ни один из них не объясняет, как установить флаг переноса, просто используя отношения между двумя операндами и результат.

Любой ответ приветствуется. Заранее спасибо.

Regard.

Ответы [ 4 ]

6 голосов
/ 18 мая 2010

Флаг переноса устанавливается обычным способом, например, в результате сложения, которое генерирует перенос. Затем вы можете использовать инструкцию ADC (добавить с переносом) для распространения этого переноса в старшее слово, например, при выполнении 64-битного добавления:

ADDS    r4, r0, r2    ; add least significant words
ADC     r5, r1, r3    ; add most significant words with carry

В этом примере 64-битное значение в r4: r5 равно сумме 64-битных значений в r0: r1 и r2: r3.

В ранних версиях ARM вы могли установить флаг переноса явно следующим образом:

ORRS R15,R15,#&20000000

или как это:

TEQP R15,#&20000000

См. Этот учебник для получения дополнительной информации: http://www.peter -cockerell.net / aalp / html / ch-3.html

Очевидно, более новые версии ARM перенесли флаг переноса в другой регистр (см. Комментарии ниже).

4 голосов
/ 18 мая 2010

Необходимо проверить справочное руководство для процессора, чтобы узнать, какие инструкции устанавливают флаги переноса и каким образом. Я не знаю достаточно о ARM, но я видел некоторые изменения в других процессорах:

  • некоторые инструкции, которые логически генерируют перенос, могут не устанавливать флаг переноса

  • некоторые инструкции могут использовать флаг переноса в качестве дополнительного неявного операнда или результата без соединения с сложением / вычитанием

  • после вычитания процессоры различаются, в каком состоянии установлен флаг переноса (т. Е. Некоторые делают это так же, как после добавления инвертированного второго операнда, другие устанавливают его в отрицание этого)

Если то, что вы хотите, это способ увидеть, должен ли быть создан перенос для добавления в C, вот два способа (первый - прямо из определения, второй - из-за поведения без знака):

unsigned w1, w2, result;
int carry;

carry = w1 > UINT_MAX-w2;

result = w1 + w2;
carry = result < w1;
3 голосов
/ 19 мая 2010

Ознакомьтесь с ARM Architecture Справочное руководство (ласково именуемое «ARM ARM»). Возможно, вам понадобится войти в систему в эти дни, но они бесплатны (прямо за соглашением «обещать не судиться с нами»).

ARM ARM имеют подробную информацию о том, когда бит C установлен и очищен для каждой команды в форме псевдокода. В ARMv5 ARM для ADCS, например,

C Flag = CarryFrom(Rn + shifter_operand + C Flag)

... и они охватывают инструкции набора команд ARM и Thumb.

(Вы заметите, что почти все арифметические инструкции в режиме Thumb всегда устанавливают флаги кода состояния, включая бит переноса; в большинстве случаев режим ARM этого не делает, если не установлен флаг S.)

(Кроме того, моя информация может быть неактуальной; я больше всего знаком с архитектурой ARMv5TE.)

3 голосов
/ 18 мая 2010

посмотрите на архиватор, который вы можете найти в источниках GDB.

Для добавления двух операндов вы можете узнать из мсбит операндов и результата, если был перенос. Или вы можете написать экспериментальный 8-битный сумматор и построить таблицу истинности.

EDIT:



#include <stdio.h>

#define BITS 2
#define MASK ((1<<BITS)-1)

unsigned int ra,rb,rc;

int main ( void )
{

    for(ra=0;ra<=MASK;ra++)
    {
        for(rb=0;rb<=MASK;rb++)
        {
            rc=ra+rb;
            printf("%u + %u = %u : %u %u %u : %u\n",ra,rb,rc,((ra>>(BITS-1))&1),((rb)>>(BITS-1))&1,((rc>>(BITS-1))&1),rc>>BITS);
        }
    }
    return(0);
}

Который производит:

0 + 0 = 0 : 0 0 0 : 0
0 + 1 = 1 : 0 0 0 : 0
0 + 2 = 2 : 0 1 1 : 0
0 + 3 = 3 : 0 1 1 : 0
1 + 0 = 1 : 0 0 0 : 0
1 + 1 = 2 : 0 0 1 : 0
1 + 2 = 3 : 0 1 1 : 0
1 + 3 = 4 : 0 1 0 : 1
2 + 0 = 2 : 1 0 1 : 0
2 + 1 = 3 : 1 0 1 : 0
2 + 2 = 4 : 1 1 0 : 1
2 + 3 = 5 : 1 1 0 : 1
3 + 0 = 3 : 1 0 1 : 0
3 + 1 = 4 : 1 0 0 : 1
3 + 2 = 5 : 1 1 0 : 1
3 + 3 = 6 : 1 1 1 : 1

Очевидный случай - когда задан msbit первого операнда и msbit второго операнда, вы собираетесь перенести этот бит. Два менее очевидных случая: когда установлен бит MSbit а, а бит MS не установлен, произошел перенос, аналогично, когда бит MS установлен и бит не установлен, был перенос .

So

carry=0
if((MSB(A))&&(MSB(B))) carry=1
if((MSB(A))&&(!MSB(ANS))) carry=1
if((MSB(B))&&(!MSB(ANS))) carry=1
...