|
|
  |
Вопрос С |
|
|
|
Jun 29 2010, 19:52
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(zltigo @ Jun 29 2010, 21:38)  Вот как написано, так пробуйте. Во всех (!) перечисленнных вариантах делается одно и то же: +8 +2 Код ;;;34 *(uint32_t *)(string += sizeof(int32_t)) = ' '; 000006 600a STR r2,[r1,#0] ;;;35 *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; 000008 604a STR r2,[r1,#4] 00000a a23b ADR r2,|L1.248| 00000c f8412f08 STR r2,[r1,#8]! ;;;36 string += 2; 000010 1c89 ADDS r1,r1,#2 ;;;37
|
|
|
|
|
Jun 29 2010, 21:13
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Jun 29 2010, 22:52)  Во всех (!) перечисленнных вариантах делается одно и то же: +8 +2 CODE ;;;34 *(uint32_t *)(string += sizeof(int32_t)) = ' '; 000006 600a STR r2,[r1,#0] ;;;35 *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; 000008 604a STR r2,[r1,#4] 00000a a23b ADR r2,|L1.248| 00000c f8412f08 STR r2,[r1,#8]! ;;;36 string += 2; 000010 1c89 ADDS r1,r1,#2 ;;;37 Выложите-ка просто целиком и без редактирования ДВА листинга, как у Вас было и как я предложил. Тогда будет видно. Пока "идеальный варинат" этого кусочка мог-бы быть такой: CODE STR r2,[r1,#0] STR r2,[r1,#4] ADR r2,...... STR r2,[r1,#8] ADDS r1,r1,#10 Все команды по 16бит и на два байта меньше относительно приведенного выше варианта. Но компилятору чего-то у уму заклинило  А что будет если так: CODE *(uint32_t *)(string + 4) = ' '; *(uint32_t *)(string + 8 ) = (uint32_t )" 0"; string += 10; P.S. Компильнул IAR-овским компилятором (слега еще подправив,но в общем, как в 73 посте) все, как задумывалось получилось и 54 байта размер кода.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 30 2010, 08:00
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Выкладываю ваш вариант. Последнее, что вы написали, тоже делал. Пара вопросов, возникших в процессе... - 1. Можно ли "заинлайнить" библиотечную функцию, ту же div, например? 2. Есть ли способ задать массив, выровненный по 4-байтовой границе? upd. Вах, получилось! Код void itoad(int number, uint8_t *string) { #define FOUR_SPACES ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 uint8_t sign; *(uint32_t *)(string) = FOUR_SPACES; *(uint32_t *)(string + 4) = FOUR_SPACES; *(uint32_t *)(string + 8) = (uint32_t)" 0"; string += 10; // *(uint32_t *)(string += sizeof(int32_t)) = ' '; // *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; // string += 2; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } 58 байтов Код ;;;31 *(uint32_t *)(string) = FOUR_SPACES; 000002 f04f3220 MOV r2,#0x20202020 ;;;32 *(uint32_t *)(string + 4) = FOUR_SPACES; 000006 600a STR r2,[r1,#0] ;;;33 *(uint32_t *)(string + 8) = (uint32_t)" 0"; 000008 604a STR r2,[r1,#4] 00000a a23a ADR r2,|L1.244| ;;;34 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa Вроде уже делал так.
|
|
|
|
|
Jun 30 2010, 09:22
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
"Шеф, все пропало!..." По команде *(uint32_t *)(string + 8) = (uint32_t)" 0"; заносится адрес строки, а не сама строка! На всякий случай, если кто-то заинтересуется, выдаю работающий код. Код void itoad(int number, uint8_t *string) { #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 #define TETRATAIL ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24 uint8_t sign; *(uint32_t *)(string) = TETRASPACE; *(uint32_t *)(string + 4) = TETRASPACE; *(uint32_t *)(string + 8) = TETRATAIL; string += 10; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } Часть листинга, обратите внимание, стоит команда LDR, а не ADR, как раньше Код ;;;31 *(uint32_t *)(string) = TETRASPACE; 000002 f04f3220 MOV r2,#0x20202020 ;;;32 *(uint32_t *)(string + 4) = TETRASPACE; 000006 600a STR r2,[r1,#0] ;;;33 *(uint32_t *)(string + 8) = TETRATAIL; 000008 604a STR r2,[r1,#4] 00000a 4a3a LDR r2,|L1.244| ;;;34 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa
|
|
|
|
|
Jun 30 2010, 11:35
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(MrYuran @ Jun 30 2010, 14:31)  Вот никак не могу понять, почему никто до сих пор не придумал оператор, который возвращает сразу и частное, и остаток. В 51-й микроЭВМ была. А в Cortex заменяется двумя командами (upd. Вернее, тремя. Исправил код). Дважды не делается. Код 000022 4602 MOV r2,r0 000024 fb90f0f3 SDIV r0,r0,r3 000028 fb032210 MLS r2,r3,r0,r2
|
|
|
|
|
Jun 30 2010, 19:02
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Jun 30 2010, 11:22)  На всякий случай.. Ну если упорно не хотите нормальное сравнение следать, то вот: CODE 59 void itoad(int number, uint8_t *string) 60 { \ itoad: \ 00000000 10B4 PUSH {R4} 61 int sign; 62 *(int32_t *) string = 0x20202020; \ 00000002 .... LDR.N R2,??DataTable1_1;; 0x20202020 \ 00000004 0A60 STR R2,[R1, #+0] 63 *(int32_t *)(string += 4) = 0x20202020; \ 00000006 4A60 STR R2,[R1, #+4] 64 *(int32_t *)(string += 4) = 0x00302020; \ 00000008 .... LDR.N R2,??DataTable1_2;; 0x302020 \ 0000000A 8A60 STR R2,[R1, #+8] 65 string += 2; \ 0000000C 0A31 ADDS R1,R1,#+10 66 if (!number) return; \ 0000000E 78B1 CBZ.N R0,??itoad_0 67 if (number > 0) sign = '+'; \ 00000010 0128 CMP R0,#+1 \ 00000012 AEBF ITEE GE \ 00000014 2B22 MOVGE R2,#+43 \ 00000016 4042 RSBLT R0,R0,#+0 \ 00000018 2D22 MOVLT R2,#+45 68 else { 69 number = -number; 70 sign = '-'; 71 } 72 do { 73 *string-- = number % 10 + '0'; \ ??itoad_1: \ 0000001A 0A23 MOVS R3,#+10 \ 0000001C 90FBF3F4 SDIV R4,R0,R3 \ 00000020 03FB1400 MLS R0,R3,R4,R0 \ 00000024 3030 ADDS R0,R0,#+48 \ 00000026 01F80109 STRB R0,[R1], #-1 74 } while (number /= 10); \ 0000002A 2000 MOVS R0,R4 \ 0000002C F5D1 BNE.N ??itoad_1 75 *string = sign; \ 0000002E 0A70 STRB R2,[R1, #+0] 76 } \ ??itoad_0: \ 00000030 10BC POP {R4} \ 00000032 7047 BX LR ;; return
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 30 2010, 20:29
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(zltigo @ Jun 30 2010, 22:02)  Ну если упорно не хотите нормальное сравнение сделать, то вот: Вы имеете в виду сравнение кода, или операции сравнения внутри кода? Почему не хочу? Еще как! Листинг я же выдал, там, в файлике keil_temp.txt (он и создается Keil-ом именно в таком виде, с расширением txt). Вот еще раз, после замены типа переменной sign (думал, может в ней дело). С недоумением разглядываю ваш и свой листинги, ничего путного на ум не приходит. Код itoad PROC ;;;27 *************************************************************************** ****/ ;;;28 void itoad(int number, uint8_t *string) 000000 b510 PUSH {r4,lr} ;;;29 { ;;;30 #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 ;;;31 #define TETRATAIL ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24 ;;;32 // uint8_t sign; ;;;33 int sign; ;;;34 *(uint32_t *)(string) = TETRASPACE; 000002 f04f3220 MOV r2,#0x20202020 ;;;35 *(uint32_t *)(string + 4) = TETRASPACE; 000006 600a STR r2,[r1,#0] ;;;36 *(uint32_t *)(string + 8) = TETRATAIL; 000008 604a STR r2,[r1,#4] 00000a 4a62 LDR r2,|L1.404| ;;;37 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa ;;;38 if (!number) return; 000010 2800 CMP r0,#0 000012 d011 BEQ |L1.56| ;;;39 if (number > 0) sign = '+'; 000014 dd02 BLE |L1.28| 000016 f04f042b MOV r4,#0x2b 00001a e001 B |L1.32| |L1.28| ;;;40 else { ;;;41 number = -number; 00001c 4240 RSBS r0,r0,#0 ;;;42 sign = '-'; 00001e 242d MOVS r4,#0x2d |L1.32| ;;;43 } ;;;44 do { ;;;45 *string-- = number % 10 + '0'; 000020 230a MOVS r3,#0xa |L1.34| 000022 4602 MOV r2,r0 000024 fb90f0f3 SDIV r0,r0,r3 000028 fb032210 MLS r2,r3,r0,r2 00002c 3230 ADDS r2,r2,#0x30 00002e f8012901 STRB r2,[r1],#-1 ;;;46 } while (number /= 10); 000032 2800 CMP r0,#0 000034 d1f5 BNE |L1.34| ;;;47 *string = sign; 000036 700c STRB r4,[r1,#0] |L1.56| ;;;48 } 000038 bd10 POP {r4,pc} ;;;49 ENDP У вас метка itoad играет какую-то роль? Почему-то у меня запоминается в стеке LR, а у вас нет. У вас в строке 63 должно быть число 0x20202020 или, как написано? Сравнение number производится по-разному, но я не вижу в исходниках разницы. И это LDR.N - там действительно будет по 2 байта? Где-то рядом таблица? Забавно, что байты в машинных кодах в IAR и Keil написаны по-разному. Где младший, где старший? Еще один прикол - у меня '+' заносится в регистр 4-байтовой командой (потому что не имеет повторяющейся последовательности?), а '-' 2-байтовой. У вас все 2-байтовые. Неужели IAR настолько лучше Keil?
|
|
|
|
|
Jun 30 2010, 21:14
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Jun 30 2010, 22:29)  У вас в строке 63 должно быть число 0x20202020 или, как написано? Следы экспериментов. Все 20 QUOTE У вас метка itoad играет какую-то роль? Не у меня, а у ASM - точка входа в эту подпрограмму. QUOTE Где-то рядом таблица? А зачем ей быть далеко? IAR Компилятор сделал все корректно и на 6 байт короче. QUOTE Почему-то у меня запоминается в стеке LR Keil решил сэкономить на BX LR
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jul 1 2010, 08:55
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Сергей Борщ @ Jun 29 2010, 17:18)  Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные. Грабли можно избежать, если определить строку в виде объединения байтов и 4-байтовых слов. 2 all: Как сделать в Keil то же, что и в IAR? Цитата(zltigo @ Jul 1 2010, 00:14)  IAR Компилятор сделал все корректно и на 6 байт короче. Только в таблице у него 8 байтов, а у Keil-а 4. Итого, с учетом таблицы, 60 байтов против 62 байтов. P.S. А тема-то, действительно, начинает соответствовать своему названию - "Вопрос C"
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|