Сборка ARMv7-M Использование ITEE

  • Проблема:

Я пытаюсь заставить блок ITEE EQ, т.е. блок 'If-Then-Else-Else Equal', работать, когда R6==0, с переходом THEN в >END, но ассемблер выдал ошибку в строке: BEQ END

  • Информация о программе:

Я делаю программу, связанную с оптимизацией. Я использую градиентный спуск, чтобы сходиться к точке, где градиент равен 0, чтобы найти решение x *, которое минимизирует некоторую функцию f (x). Я использую язык C для вызова ассемблерной функции, которой является вот эта программа.

Вот моя программа, где ошибка:

        CMP R6, #0          @ Compare f'(x) with 0
        ITEE EQ             @ If R6 == 0, Then-Else-Else
        BEQ END             @ Calls END label if equal
        SUBNE R0, R6        @ Change R0(x) in the opp direction of gradient to get lower value of f(x) if not equal
        BNE optimize        @ Branch to optimize if not equal

Это моя первая программа сборки, использующая NXP LPC1769 для школьного задания. Дайте мне знать, что мне не хватает или я сделал неправильно. Благодарю вас!

Вот вся моя программа:

.syntax unified
.cpu cortex-m3
.thumb
.align 2
.global optimize
.thumb_func

optimize:
@  Write optimization function in assembly language here

        MOV R5, INLAMBDA    @ R5 holds value of inverse lambda(10) ie to eliminate floating point
        LDR R6, #2          @ Load R6 with value '2' ie constant of f'(x)
        MUL R6, R1, R6      @ Multiply R6(2) with R1(a) & store to R6(results)
        MLA R6, R6, R0, R2  @ Multiply R6(results) with R0(x) & sum with R2(b) to get f'(x). Store & update results to R6
        SDIV R6, R5         @ Divide R6(results) by R5(1/lambda) to get f'(x) * lambda

        CMP R6, #0          @ Compare f'(x) with 0
        ITEE EQ             @ If R6 == 0, Then-Else-Else
        BEQ END             @ Calls END label if equal
        SUBNE R0, R6        @ Change R0(x) in the opp direction of gradient to get lower value of f(x) if not equal
        BNE optimize        @ Branch to optimize if not equal

@  End label
END:

BX LR

@ Define constant values
CONST: .word 123
INLAMBDA: .word 10      @ Inverse lambda 1 / lambda(0.1) is 10

person Adeep    schedule 31.08.2016    source источник
comment
В сообщении об ошибке было сказано, в чем именно заключается проблема: Error: branch must be last instruction in IT block -- 'beq END'   -  person Ross Ridge    schedule 31.08.2016
comment
Если только это не была, скажем, ошибка armasm: A1603E: Эта инструкция внутри блока IT имеет НЕПРЕДСКАЗУЕМЫЕ результаты, что гораздо менее ясно, или, возможно, какой-то другой, еще менее полезный ассемблер. В любом случае всегда полезно включать конкретное сообщение об ошибке в сам вопрос, не в последнюю очередь потому, что первое, что многие люди делают с незнакомой ошибкой, — это вставляют ее в поисковую систему, чтобы посмотреть, что появится.   -  person Notlikethat    schedule 31.08.2016


Ответы (1)


Проблема в том, что BEQ END находится в середине IT-блока. Процитирую некоторую документацию по IT:

Ветвь или любая инструкция, которая изменяет PC, разрешена в блоке IT только в том случае, если это последняя инструкция в блоке.

Тем не менее, поскольку это ветвь, "else" в любом случае неявно - если вы выберете ветвь, вы не будете выполнять следующие инструкции из-за того, что находитесь в другом месте, а если вы этого не сделаете, считайте, что у вас нет другого выбора, кроме как выполнить их, поэтому нет необходимости в том, чтобы они были явно условными. На самом деле, вам даже не нужен IT, так как B<cond> имеет правильную кодировку инструкции Thumb сама по себе. Но тогда вам даже не нужно это, потому что вы выполняете короткую прямую ветвь, основанную на нулевом регистре, и есть специальная инструкция сравнения и ветвления только для большого пальца для точного выполнения тот!

Другими словами, ваш первоначальный 5-строчный фрагмент можно выразить просто так:

CBZ R6, END
SUB R0, R6
B optimize 
person Notlikethat    schedule 31.08.2016
comment
Я никогда раньше не видел CBZ. Это отличная небольшая инструкция. - person rjp; 31.08.2016