ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Вот как написано, так пробуйте. Во всех (!) перечисленнных вариантах делается одно и то же: +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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Во всех (!) перечисленнных вариантах делается одно и то же: +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 Выложите-ка просто целиком и без редактирования ДВА листинга, как у Вас было и как я предложил. Тогда будет видно. Пока "идеальный варинат" этого кусочка мог-бы быть такой: STR r2,[r1,#0] STR r2,[r1,#4] ADR r2,...... STR r2,[r1,#8] ADDS r1,r1,#10 Все команды по 16бит и на два байта меньше относительно приведенного выше варианта. Но компилятору чего-то у уму заклинило :( А что будет если так: *(uint32_t *)(string + 4) = ' '; *(uint32_t *)(string + 8 ) = (uint32_t )" 0"; string += 10; P.S. Компильнул IAR-овским компилятором (слега еще подправив,но в общем, как в 73 посте) все, как задумывалось получилось и 54 байта размер кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Выкладываю ваш вариант. Последнее, что вы написали, тоже делал. Пара вопросов, возникших в процессе... - 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 Вроде уже делал так. keil_temp.txt Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба "Шеф, все пропало!..." По команде *(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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба 16-битовая версия (на основе 32-битовой) void i16toad(int16_t number, uint8_t *string) { #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 #define TETRATAIL ' ' | '0' << 8 | '\0'<< 16 | '\0'<< 24 uint8_t sign; int32_t num = (int32_t)number; *(uint32_t *)string = TETRASPACE; *(uint32_t *)(string + 4) = TETRATAIL; string += 5; if (!num) return; else if (num > 0) sign = '+'; else { sign = '-'; num = -num; } do { *string-- = num % 10 + '0'; } while (num /= 10); *string = sign; } Те же 58 байтов, но нет константы 4-байтовой. 105 тактов для -32767. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Вот никак не могу понять, почему никто до сих пор не придумал оператор, который возвращает сразу и частное, и остаток. Ведь они оба образуются при операции деления. Зачем 2 раза проводить одну и ту же операцию, чтобы взять по очереди две половинки результата? :laughing: Тяжёлое наследие бейсика... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Вот никак не могу понять, почему никто до сих пор не придумал оператор, который возвращает сразу и частное, и остаток. В 51-й микроЭВМ была. А в Cortex заменяется двумя командами (upd. Вернее, тремя. Исправил код). Дважды не делается. 000022 4602 MOV r2,r0 000024 fb90f0f3 SDIV r0,r0,r3 000028 fb032210 MLS r2,r3,r0,r2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Напоследок - проверил вариант с преобразованием в 4.28, для int16, с той же формой выдачи результата. Получилось 100 байтов, 150 циклов, не лучший способ. В-общем, вариант itoa для Cortex для себя я уже выбрал :). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Получилось 100 байтов, 150 циклов, не лучший способ. Ну, этот способ я выбирал с учетом специфики ARM7 - там картина должна быть противоположной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Ну, этот способ я выбирал с учетом специфики ARM7 - там картина должна быть противоположной. Я понял. Сложнее поставить знак в нужное место, и для гашения лидирующих нулей нужна переменная. Зато вместо деления - умножение. В-общем, все наоборот. Идея интересная - поделить число на 10000 и умножить на 2^28 (для других размерностей можно использовать другие числа, например, для 8-битов - использовать форму 4.12, умножив на 41). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба На всякий случай.. Ну если упорно не хотите нормальное сравнение следать, то вот: 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Ну если упорно не хотите нормальное сравнение сделать, то вот: Вы имеете в виду сравнение кода, или операции сравнения внутри кода? Почему не хочу? Еще как! Листинг я же выдал, там, в файлике 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? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба У вас в строке 63 должно быть число 0x20202020 или, как написано? Следы экспериментов. Все 20 У вас метка itoad играет какую-то роль? Не у меня, а у ASM - точка входа в эту подпрограмму. Где-то рядом таблица? А зачем ей быть далеко? IAR Компилятор сделал все корректно и на 6 байт короче. Почему-то у меня запоминается в стеке LR Keil решил сэкономить на BX LR Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 30 июня, 2010 Опубликовано 30 июня, 2010 · Жалоба Тяжёлое наследие бейсика... Это просто обязано быть отдано на откуп оптимизатору, иначе ломается синтаксис арифметического выражения. Тернарные операции с двумя значениями - это невозможно использовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 июля, 2010 Опубликовано 1 июля, 2010 · Жалоба Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные. Грабли можно избежать, если определить строку в виде объединения байтов и 4-байтовых слов. 2 all: Как сделать в Keil то же, что и в IAR? IAR Компилятор сделал все корректно и на 6 байт короче. Только в таблице у него 8 байтов, а у Keil-а 4. Итого, с учетом таблицы, 60 байтов против 62 байтов. P.S. А тема-то, действительно, начинает соответствовать своему названию - "Вопрос C" :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться