ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
26 ноября
80777 Топик полностью
AVR (10.02.2007 13:32, просмотров: 1) ответил ReAl на Ну вот, дальше пошло, теперь убирать нехорошо... По объёму кода он эффективнее, там (я написал задачи) это было важнее.
О чем я и толкую - для разных архитектур и задач оптимальное решение может быть разным Вот мой код для dsPIC: <asm> ;------------------------------------------------------------------ ; Converts an unsigned integer N in w0 to a 5-byte ASCII numerical string [w4] ; using a reciprocal multiplication and fractional conversion techniques ; 19 clocks including RETURN, 13 program words itoa: rev10k = 429497 ; ~= 2^32/10000 mov #rev10k >> 16,w1 ; Convert integer to fractional (equivalent to N/0.65536) mul.uu w1,w0,w2 ; w3:w2 = partial product MSWs mov #rev10k & 0xFFFF,w1 mul.uu w1,w0,w0 ; w1:w0 = partial product LSWs add w1,w2,w0 ; w0 = fract(N%10000) mov #'0',w2 ; w2 = ASCII bit mask, will also be used later addc.b w3,w2,[w4++] ; w3 = N/10000, store an ASCII MS character inc w0,w0 ; Correct a remainder to use 16-bit ops do #3,1f ; Repeat the following code 4 times mul.uu w0,#10,w0 ; w1 = next ASCII digit (0..9 range), w0 = fractional remainder 1: ior.b w1,w2,[w4++] ; Store a next ASCII character return ;------------------------------------------------------------------ </asm> Здесь я использовал совершенно другой алгоритм - сначала преобразовал integer во fractional, а потом уже полученный fractional преобразовывал в десятичный вид, последовательно умножая этот fractional на 10. На С этот код будет эффективно перевести достаточно затруднительно, да и эффективным он будет только для конкретной архитектуры - dsPIC. Для AVR я тоже сделал пробный itoa по этому же принципу - оказалось весьма недурственно (код можно запросто свернуть раза в полтора, загнав mul10 в цикл): <asm> ;-------------------------------------------------------------------- ; Converts an unsigned integer r5:r4 to a 5-character ASCII string [x] ; 58 program words, 73 clocks + ret itoa: .equ rev10k = 429497 ; ~= 2^32/10000 clr r2 ldi r16,low(rev10k) ldi r17,high(rev10k) ldi r18,byte3(rev10k) mul r4,r16 mov r6,r1 mul r4,r17 add r6,r0 adc r1,r2 mov r7,r1 mul r4,r18 add r7,r0 adc r1,r2 mov r8,r1 ; r8r7r6 ~= Xlsb*429497/256, 06872B max mul r5,r16 add r6,r0 adc r7,r1 adc r8,r2 mul r5,r17 add r7,r0 adc r8,r1 mul r5,r18 add r8,r0 ; r8r7 ~= int2fract(X%10000) ldi r17,'0' adc r1,r17 ; r1 = ASCII(X/10000) st x+,r1 ; Tens of thousands ;-------------------------------------------------------------------- ; Converts fractional 16-bit value in r5:r4 (0..9999) range ; to a 4-character ASCII string [x] ; by sequential multiplication by 10 fractoa: ldi r16,10 ; Constant for multiplication by 10 sec ; Correct int2fract result to fit in 16-bit word adc r7,r2 ; by incrementing it adc r8,r2 ; mul r7,r16 ; Multiply a 16-bit value by 10 movw r2,r0 ; mul r8,r16 ; add r3,r0 ; r3r2 ~= int2fract(X%1000) adc r1,r17 ; r1 = ASCII(X/1000) st x+,r1 ; Thousands mul r2,r16 ; Same as above for hundreds movw r4,r0 mul r3,r16 add r5,r0 adc r1,r17 st x+,r1 mul r4,r16 ; Same as above for tens movw r2,r0 mul r5,r16 add r3,r0 adc r1,r17 st x+,r1 mul r2,r16 ; Same as above for units movw r4,r0 mul r3,r16 add r5,r0 adc r1,r17 st x+,r1 ret ;-------------------------------------------------------------------- </asm>