4-Feb-04 20:28 Vladimir Chekin wrote to Kirill Frolov:
KF>> void Reset2() { KF>> asm("bcf status_reg, _other_bit"); KF>> }
KF>> void Reset1() { KF>> asm("bcf status_reg, _some_bit"); KF>> Reset2(); KF>> } VC> Совсем не то же самое. Скомпили свои примеры. В лучшем случае ты VC> получишь 2 VC> ретурна с разными адресами в кодовой памяти и goto _Reset2 в функции VC> Reset1, а в моём примере один return и никаких goto.
VC> PS: это был пример (ака предположение) как я понимаю термин Я тоже понял именно так.
Насколько я помню, просили "хотя бы один С-компилятор", который сможет такое (с заменой call+ret на jmp смогут довольно многие).
Вы этого хотели -- нате: Тут надо немного помочь компилятору - он как правило не умеет переставлять местами функции.
======================= _tail.c #include <io4433.h>
void Reset2(void);
void Reset1(void) { PORTB &= ~0x01; Reset2(); }
void Reset2(void) { PORTB &= ~0x02; } ====================== _tail.lst
# IAR AT90S C-Compiler V1.40E/386 [demo] # Compile time = 04/Feb/2004 22:58:28 # Target option = Max 64 KB data + 8 KB code (8515 4414...) # Memory model = tiny # Source file = _tail.c # List file = _tail.lst # Object file = _tail.r90 # Command line = -f EXPONTST.cfg (-S -e -K -g -v1 -mt # -Ic:\IAR\EW22DEMO\A90\INC\ -I..\..\..\common\ # -I..\..\..\common\AVR\) -z9 _tail.c -q -l # _tail.lst # (c) Copyright IAR Systems 1998
1 #include <io4433.h>
2 3 void Reset2(void); 4 5 void Reset1(void) { \ Reset1: 6 PORTB &= ~0x01; \ 00000000 C098 CBI LOW(24),LOW(0) 7 Reset2(); 8 } 9 10 void Reset2(void) { \ Reset2: 11 PORTB &= ~0x02; \ 00000002 C198 CBI LOW(24),LOW(1) 12 } \ 00000004 0895 RET
Keil C51 такого сделать не может в принципе, так как он каждую функцию помещает в отдельный сегмент, чтобы плотнее упаковывать код. Дело в том, что в модели ROM(COMPACT) он считает, что каждая функция будет меньше 2K и внутри функции пользует ajmp, устанавливая соответствующую опцию секции кода (inblock - не переезжать секцией через граница 2K). После растасовки таких функций остаются дырочки, в которые успешно влазят подобные короткие функции.
gcc тут сплоховал, не умеет он такое. Зато умеет такое :-)
unsigned foo( unsigned u) { return (u>>3) | (u<<29); }
_foo: movl 4(%esp), %eax roll $29, %eax ret
wbr, p.s. естественно, все тонкости С-компиляторы не учитывают. Но всё равно на достаточно большом проекте выигрыш ассемблера не настолько велик, чтобы тратить на него время. Редко когда имеет смысл делать на нём больше 10-15% кода проекта.