Keil arm Cortex — найти среднее число из 3

#assembly #keil #cortex-m

#сборка #keil #cortex-m

Вопрос:

Допустим, я загружаю 3 числовых значения в три разных регистра. И я хочу найти среднее число.

 AREA median, CODE, READONLY
    EXPORT main
first  EQU 3
middle EQU 3
last   EQU 9
    ENTRY

main 
     MOV R0, #first
     MOV R1, #middle
     MOV R2, #last
----------
Here i would like to compare these 3 values and find the middle number. (in this case, 3)
  

Я пробовал что-то вроде CMP R1, R2 , но мне не удалось сохранить значение, которое я хотел, в регистре. Это то, что я пытался найти, меньшее или большее из двух.

 main:
        mov     r1, #3     /* setting up initial variable a */
        mov     r2, #9     /* setting up initial variable b */
        cmp     r1, r2     /* comparing variables to determine which is bigger */
        blt     r1_lower   /* jump to r1_lower in case r2 is bigger  */
        mov     r0, r1     /* if branching/jumping did not occur, r1 is bigger (or the same) so store r1 into r0 */
        b       end        /* proceed to the end */
r1_lower:
        mov r0, r2         /* end up here because r1 was smaller than r2, so move r2 into r0 */
        b end              /* proceed to the end */
  

Есть мысли?

Комментарии:

1. Каково начальное значение r0 ?

2. @fuz Начальное значение r0 равно 0x00

3. Для алгоритма, я думаю, вам нужно 3 сравнения. Для получения минимального или максимального значения требуется всего 2, но вы не можете исключить любое значение в качестве возможного среднего после первого сравнения.

Ответ №1:

Конкретно для трех чисел существует два основных подхода:

  • вы можете отсортировать три числа и вернуть среднее число из отсортированного массива. Для этого обычно полезна трехступенчатая сеть сортировки. Для сборки этого используйте этот примитив, который меняет местами r0 и r1 , если r0 больше, чем r1 , используя r3 в качестве временного регистра:

     cmp   r0, r1     # if (r0 > r1)
    movgt r3, r1     #         r2 = r1
    movgt r1, r0     #         r1 = r0
    movgt r0, r3     #         r0 = r1
      
  • в качестве альтернативы вы можете вычислить максимальное и минимальное из трех чисел и вычесть его из их суммы, получив среднее число. Например, если три числа находятся в r0 , r1 и r2 , это может быть сделано с помощью:

     cmp       r0, r1 # if (r0 > r1)
    movgt r3, r0     # then r3 = r0  (r3 is max)
    movgt r4, r1     # then r4 = r1  (r4 is min)
    movle r3, r1     # else r3 = r1
    movle r4, r0     # else r4 = r0
    cmp       r2, r3 # if (r2 > r3)
    movgt r3, r2     # then r3 = r2
    cmp       r4, r2 # if (r4 > r2)
    movgt r4, r2     # then r4 = r2
    add   r5, r0, r1 # r5 = r0   r1  (r5 is middle)
    add   r5, r5, r2 # r5 = r5   r2
    sub   r5, r5, r3 # r5 = r5 - r3
    sub   r5, r5, r4 # r5 = r5 - r5
      

Ответ №2:

С какой именно проблемой вы столкнулись? Ваша CMP инструкция в порядке и установит флаги состояния в зависимости от относительных значений R0 и R1 , поэтому затем вы можете использовать условную ветвь (например, BHI or BGT ) или одну из IT семейства инструкций, которая позволит вам выполнять другие инструкции условно, используя те же коды условий.

Здесь есть краткий справочник по набору команд Thumb-2 (используемому большинством устройств Cortex-M, которые, как я предполагаю, вы используете в отсутствие какой-либо другой информации), а также множество дополнительной документации по условному ветвлению и условному выполнению на сайте ARM Infocenter, например, здесь для Cortex-M3.