ljr - Юра Бронников - Ассемблер ARM [entries|archive|friends|userinfo]
Юра Бронников

[ userinfo | ljr userinfo ]
[ archive | journal archive ]

Ассемблер ARM [Dec. 15th, 2009|01:26 am]
Previous Entry Add to Memories Tell A Friend Next Entry
У меня сейчас завелось вычислительное устройство с таким процессором,
-- о нем еще будет отдельный пост, -- и я, наконец, решил
поинтересоваться, как устроена тамошняя система команд. И мне
понравилось.


Во-первых, это вполне честный 32-битный RISC, с 16-ю целочисленными
регистрами (есть еще какие-то дополнительные для привилегированных
режимов). Указатель стека, счетчик команд, а также link register
(как по-русски?) и указатель кадра (frame pointer) входят в число этих
шестнадцати. Некоторые команды, вроде переходов и вызова подпрограмм,
работают с ними особым образом, но с тем же успехом к ним можно
обращаться и обыкновенными командами для пересылки значений и
арифметики. Например,
	b	.L5

-- команда перехода на метку .L5, а
	ldr	pc,.L10 
	...
.L10:	.word	.L5

-- загрузка слова в регистр, которая делает то же самое.

Как полагается, в отдельном регистре хранятся флаги состояния. И,
опять же, как полагается, условные переходы могут производиться или не
производиться в зависимости от значения этих флагов. Разница с
привычными мне другими системами команд в том, что, во-первых, при
каждой арифметической команде можно указать, будет она выставлять
флаги или нет (видимо, в формате инструкции просто заготовлен для
этого битик), а во-вторых, выполнять или не выполнять в зависимости
от флагов тоже можно любую команду, а не только переходы -- тоже,
наверное, есть просто особое поле в формате команды. В результате
можно делать, например, так: сишный код
int
qq (int a, int b, int c, int d)
{
  if (a+b < 0) {
    return a+b+c+d;
  } else {
    return a+b-c+d;
  }
}

команда
 
	gcc -S -Os tt.c

переводит в
qq:
	@ Параметры передаются в регистрах r0 (a), r1 (b), r2 (c)
	@ и r3 (d).
	@ Результат ожидается в r0.
	adds	r1, r1, r0	@ Получаем a+b  в регистре r1.
		    		@ При этом устанавливаем флаги
				@ (за это отвечает буква s).
	addmi	r1, r2, r1	@ Получаем в r1 a+b+с. Но делаем это
		    		@ только в том случае, когда флаги,
				@ полученные предыдущей командой,
				@ показывают минус (mi).
				@ Эта команда флаги не ставит.
	rsbpl	r0, r2, r3      @ А это команда с ветки else,
		    		@ поскольку имеет в имени pl,
				@ то есть, ждет неотрицательных флагов.
				@ (не знаю, почему gcc именно так их
				@ упорядочил). Она кладет в r0
				@ разницу c и d.
	addmi	r0, r1, r3	@ Вторая команда ветки then. Флаги
		    		@ по-прежнему действуют те, которые
				@ утстановлены первым сложением.
	addpl	r0, r0, r1	@ Вторая команда ветки else.
	bx	lr		@ Возврат.

Как видим, в теле функции нет никаких переходов.

Обращение к элементу целочисленного массива может выглядеть так:
	ldr	r0, [r2, r3, asl #2]

Здесь r2 -- адрес начала массива, r3 -- индекс в нем, но поскольку
целые занимают по четыре байта, прежде,
чем добавить его к базовому адресу, надо его сдвинуть влево на два
(asl #2). Опять-таки, такой сдвиг можно вставить в любую команду --
может, мы, например хотим получить адрес начала восьмибайтовой
структуры в регистре:
	add	r1, r0, r1, asl #3

А вот как выглядит
 
       k = *(--pp)

-- вот так:
	ldr	r2, [r1, #-4]!

То есть сначала r1 уменьшается на 4, а потом по получившемуся адресу
идет обращение. Кроме такого преинкремента есть, разумеется, и
постинкремент -- было бы желание.

В заголовке функции бывает нужно сохранить регистры на стеке:
	stmfd	sp!, {r4, lr}

Какие именно регистры сохранять, указывается битовой маской, а
восклицательный знак говорит, что указатель стека надо в результате
подвинуть. Соответственно, стек восстанавливается так:
	ldmfd	sp!, {r4, lr}

Lr (link register) при вызове подпрограммы содержит адрес
возврата. Соответственно, говорит учебник, при желании вместо команд
	ldmfd	sp!, {r4, lr}
	bx lr

можно вернуться просто через
	ldmfd	sp!, {r4, pc}

Но почему-то компилятор такого не порождает. (Мешает предсказанию ветвлений?)

В общем, вроде все простенько, ничего особенного, но все к месту. И,
кстати, очень похоже на мою любимую PDP-11. Я почти наверняка ничего
на этом ассемблере писать никогда не буду, но само ощущение, что в
моем компьютере живет такой зверь, а не уебище x86, прибавляет радости
при общении с ним.
LinkLeave a comment

Comments:
[User Picture]
From:[info]yushi
Date:December 15th, 2009 - 01:25 am
(Link)
но само ощущение, что в моем компьютере живет такой зверь, а не уебище x86

Неужто кто-то довёл до товарного состояния долгожданные ARM'овые нетбуки? NVIDIA?
[User Picture]
From:[info]gogabr
Date:December 15th, 2009 - 01:41 am
(Link)
Нет. TouchBook.
Состояние я пока не стал бы называть товарным.
From:[info]alexott.livejournal.com
Date:December 15th, 2009 - 09:25 am
(Link)
а когда оно сложено в таблетку, у него клавиатурные клавиши не нажимаются?
P.S. ассемблер PDF-11 это да, хорошая вещь была. мне еще нравилась система команд VAX, с трехоперандными командами
[User Picture]
From:[info]gogabr
Date:December 15th, 2009 - 09:33 am
(Link)
Таблетка от клавы просто отстегивается.
Подожди уж, собираюсь написать подробно.
From:[info]alexott.livejournal.com
Date:December 15th, 2009 - 09:34 am
(Link)
жду :-)
[User Picture]
From:[info]yushi
Date:December 15th, 2009 - 10:35 am
(Link)
Ага. Ну, с нетерпением ждём отдельный пост.
From:[info]tristes_tigres
Date:December 15th, 2009 - 01:40 pm
(Link)
Плавающая точка аппаратная есть ?
[User Picture]
From:[info]gogabr
Date:December 15th, 2009 - 06:42 pm
(Link)
В исходном наборе нет.
В этом конкретном процессоре что-то есть, не разбирался пока.