* C for Dummies * Aleph * 2000-09-11 * 011 *
-----[00]----------[Quote of Day]-----------------------------------------
If you think education is expensive, try ignorance
Derek Bok
-----[01]----------[Hot News]---------------------------------------------
Turbo Dump Version 5.0.13 Утилита фирмы Borland для просмотра и
извлечения информации из двоичных файлов (.OBJ, .LIB, EXE).
http://members.xoom.com/c4dummies/files/tdump.zip (73,060)
-----[02]----------[Blah-Blah-Blah]---------------------------------------
Основополагающий принцип Дзюдо обычно переводят как "Победа - слабому",
утверждая примат отточенной техники над грубой силой.
Символичный бросок десятилетней японской девочки Natsumi Gomi, повергшей
на татами российского президента, прекрасная тому иллюстрация.
News:
http://news.lycos.com/headlines/Entertainment/Oddly-Enough/article.asp?docid=RTODD-PUTIN-DC&date=20000905
http://dailynews.yahoo.com/h/nm/20000905/od/putin_dc_1.html
Photo:
http://dailynews.yahoo.com/h/p/nm/20000906/wl/imdf85941.html
http://dailynews.yahoo.com/h/p/nm/20000906/wl/imdf85942.html
а также здесь (новости + фото):
"Putin Proves Pushover for Girl - on Judo Mat"
(Reuters/Toshiyuki Aizawa/Tokyo)
http://members.xoom.com/c4dummies/files/judo.zip (64,251)
В программировании отточенная техника также намного важнее грубой силы,
хотя есть ситуации, где применима только лобовая атака (Brute force).
Но всякий раз, встретив новую для себя проблему, прежде всего пытайтесь
нащупать ее "болевые точки", и тогда отточенный прием может разрешить все
Ваши затруднения.
-----[03]----------[Topic]------------------------------------------------
Pointers. Data Types. Declarations.
-----[04]----------[Body]-------------------------------------------------
Pointers
--------
> Указатели типа FAR
> ------------------
>
> Указатель типа far (32-битный) содержит не только смещение в сегменте,
> а также (как другую 16-битную величину) адрес сегмента, который затем
> сдвигается влево и добавляется к смещению. Используя far-указатели, вы
> можете иметь множественные программные сегменты, что позволяет
> создавать программы величиной более 64К. Таким же образом far-указатели
> могут адресовать данные, занимающие более 64К памяти.
>
> Когда вы используете far-указатели к данным, вы должны знать о
> потенциальных проблемах в манипулировании указателями. Как объяснялось
> в разделе "Вычисление адреса", вы можете иметь много различных пар
> "сегмент:смещение", указывающих на один и тот же адрес. Например, все
> far- указатели 0000:0120, 0010:0020 и 0012:0000 указывают на один и тот
> же 20-битный адрес. Однако, если вы имеете 3 различных переменных
> far-указателя - a, b и c, содержащие эти 3 величины соответственно, то
> все следующие выражения будут работать неправильно:
>
> if (a==b) ...
> if (b==c) ...
> if (a==c) ...
>
> Указанная проблема появляется, когда вы хотите сравнить far- указатели,
> используя операторы >, >=, <, <=. В этих случаях только смещение (как
> беззнаковое) может использоваться в целях сравнения. Предположим, что
> а, b и c имеют значения, описанные выше; тогда следующие выражения
> будут верны:
>
> if (a>b) ...
> if (b>c) ...
> if (a>c) ...
>
> Операторы равенства (==) и неравенства (!=) используют 32-битную
> величину как unsigned long (беззнаковую длину),а не как полный адрес
> памяти. Операторы сравнения ( >, >=, < и <=) используют только
> смещение.
>
> Для операторов == и != необходимы все 32 бита для того, чтобы можно
> было произвести сравнение с NULL указателем (0000:0000).В противном
> случае, если для проверки равенства вы используете только смещение, то
> любой указатель со смещением 0000 будет равен NULL указателю, а это не
> является тем, что вы хотите.
>
> Еще вам необходимо знать следующее. Если вы прибавляете величину к
> far-указателю, то изменяется только смещение. Если результат сложения
> превышает величину FFFF (это максимально возможная величина смещения),
> то указатель делает циклический переход назад, к началу сегмента.
> Например, результатом прибавления 1 к 5031:FFFF, будет 5031:0000 (а не
> 6031:0000). Аналогично, если вы вычитаете 1 из 5031:0000, то получите
> 5031:FFFF (а не 5030:000F).
>
> Если вы хотите сравнить указатели, то надежнее использовать или
> near-указатели, которые всегда используют один и тот же адрес сегмента,
> или huge-указатели, описание которых следует далее.
>
>
> Указатели типа HUGE
> -------------------
>
> Указатели типа huge (также как и far) имеют 32-битную длину и содержат
> как адрес сегмента, так и смещение. Однако, в отличие от far, они
> нормализованы с целью решения проблем, рассмотренных в предыдущем
> разделе.
>
> Что такое указатель типа huge ? Это 32-битный указатель, который имеет
> наибольшую из возможных величину адреса сегмента. Так как сегмент
> всегда начинается с адреса, кратного 16 (или 10h), то это означает, что
> смещение может принимать значения от 0 до 15 (от 0h до Fh).
>
> Как нормализовать указатель ? Очень просто: переведите его в 20-битный
> адрес, затем используйте правые 4 бита для смещения и левые 16 бит для
> адреса сегмента. Например, дан указатель 2F84:0532; мы переведем его в
> абсолютный адрес 2FD72, который затем нормализуется в 2FD7:0002.
> Приведем несколько указателей и их нормализованные значения:
>
> 0000:0123 0012:0003
> 0040:0056 0045:0006
> 500D:9407 594D:0007
> 7418:D03F 811B:000F
>
> Теперь вы знаете, что указатели типа huge всегда хранятся
> нормализованными. Почему это важно ? Потому, что для любого данного
> адреса памяти имеется только один возможный указатель типа huge - пара
> "сегмент:смещение". Это означает, что операторы >, >=, <, <= дадут
> правильный ответ для любого указателя типа huge.
>
> Дополнительно к этому, все операторы >, >=, <, <= используют полную
> 32-битную величину указателя типа huge. Нормализация гарантирует, что
> их результат всегда будет корректным.
>
> И, наконец, благодаря нормализации, смещение в указателе типа huge
> автоматически делает циклический переход, при достижении величины 16,
> но, в отличие от far, сегмент также увеличивается. Например, если вы
> увеличиваете 811B:000F, то результат будет 811C:0000; аналогично, если
> вы уменьшаете 811C:0000, то получите 811B:000F. Эта особенность
> указателей типа huge позволяет манипулировать структурами данных свыше
> 64К.
>
> Однако при использовании указателей типа huge возрастают дополнительные
> расходы. Арифметические операции над указателями типа huge выполняются
> с вызовом специальных подпрограмм, и поэтому они выполняются гораздо
> медленнее, чем над указателями типа near и far.
Data Types
----------
В пятом выпуске мы уже немного говорили о типах данных (применительно к
константам). Приведу сводную таблицу еще раз.
> Типы данных, размеры и диапазоны в Турбо Си
> -----------------------------------------------------------------
> Тип Размер (в битах) Диапазон
> -----------------------------------------------------------------
>
> unsigned char 8 0 - 255
> char 8 -128 - 127
> enum 16 -32768 - 32767
> unsigned short 16 0 - 65535
> short 16 -32768 - 32767
> unsigned int 16 0 - 65535
> int 16 -32768 - 32767
> unsigned long 32 0 - 4294967295
> long 32 -2147483648 - 2147483647
> float 32 3.4E-38 - 3.4E+38
> double 64 1.7E-308 - 1.7E+308
> long double 80 3.4E-4932 - 1.1E+4932
> pointer 16 (указатели near,_cs,_ds,_es,_ss)
> pointer 32 (указатели far, huge)
Вы можете видеть, что С предоставляет очень ограниченный набор базовых
типов, напрямую имплементирующих машинные типы данных. Но их правильным
выбором достигается машинная независимость.
Основой является байт - наименьший непосредственно адресуемый участок
памяти. Как правило, размер байта - 8 бит (сокращение от binary digit -
двоичная единица, разряд).
Размеры всех других типов всегда кратны байту.
В С байт отображается на самый короткий целый тип - char - символьный.
Для указания компилятору, как именно трактовать это целое - со знаком
или без - используются два модификатора:
signed - знаковый
unsigned - беззнаковый.
По умолчанию (опасный принцип, неизжитый со времен Fortran'а), все целые
типы трактуются как signed и сам этот модификатор в таком случае может
быть опущен.
Иными словами, записи char и signed char для компилятора эквивалентны.
Но, на самом деле, TC 2.0 предоставляет Вам несколько большую свободу:
Вы можете зайти в Options | Compiler | Code generation | Default char type
и выбрать между знаковым и беззнаковым типом по умолчанию.
File Edit Run Compile Project Options Debug Break/watch
+------------------------------------ Edit+------------------+-----------------+
| Line 1 Col 1 Insert Indent Ta| Compiler |NONAME.C |
| | +---------------------------+ |
| | | Model Small | |
| | | Defines | |
| | | Code generation | |
| +--------------------------------------+|
| | Calling convention C ||
| | Instruction set 8088/8086 ||
| | Floating point Emulation ||
| | Default char type Signed ||
Беззнаковый тип - это всегда положительное число, подчиняющееся обычным
правилам арифметики по модулю, определяемом разрядностью регистра. Так,
при разрядности байта в восемь бит, модуль равен 8.
Разрядность (число байт) в типах short, int и long оставляется на
усмотрение разработчиков компиляторов и, вообще говоря, может совпадать.
Единственное (и естественное) требование: int не должен быть короче short,
а long не должен быть короче int.
На IBM/PC в 16-ти разрядных системах (DOS, Win16) совпадают short и int, в
32-х разрядной среде (Win32) совпадают int и long.
На других компьютерах (других OS) или в компиляторах других фирм это может
быть не так.
Всегда будьте предельно осмотрительны, если работа Вашей программы зависит
от размерности данных.
В данной реализации (TC 2.0) символьный тип char всегда имеет размер 1
байт, int - 2, и long - 4. С любым из этих трех типов Вы можете
использовать модификаторы signed и unsigned.
Обычно, разрядность типа int совпадает с длиной машинного слова (в данном
случае - 2 байта).
Кроме того, существует еще один, очень специальный, целый тип - enum (от
enumeration - перечисление), о котором мы поговорим позднее. Обычно, enum
имеет такую же разрядность как и int и может приводиться к другому целому
типу подходящего размера.
Числа с плавающей точкой могут иметь один из трех типов: float, double и
long double, в зависимости от требуемой точности. Практически все
библиотечные функции для работы с плавающей точкой принимают и возвращают
тип double, а тип long double не имеет почти никакой поддержки.
Размер указателя (16 или 32 бит) будет зависеть от выбранной модели памяти
и использованного модификатора: near, far, huge.
Напомню еще раз, что нормализуются только указатели типа huge, и
необходимо быть предельно внимательным с адресной арифметикой.
По счастью, в Win32 (flat memory model) Вы будете избавлены от этой
головной боли.
Declarations
------------
C требует опережающего объявления всех используемых переменных - большой
шаг к безопасному программированию по сравнению с Fortran или Basic.
В отличие от C++, где объявление допускается почти в любом месте блока, в
C объявления делаются только в начале блока. (О блоке Вам пока достаточно
знать, что это все, что помещено между фигурными скобками '{' и '}' ).
Каждый оператор в языке С должен оканчиваться символом ';' (semicolon).
Примеры деклараций:
/* ****************************************************************** **
@@ DECL - A program for testing Declarations
** ****************************************************************** */
void main()
{
unsigned char c1;
signed char c2;
char c3;
unsigned short s1;
signed short s2;
short s3;
unsigned int i1;
signed int i2;
int i3;
unsigned long l1;
signed long l2;
long l3;
float f;
double d;
long double ld;
}
/* ****************************************************************** **
@@ The End
** ****************************************************************** */
Выберем односегментную модель памяти (Tiny):
File Edit Run Compile Project Options Debug Break/watch
+------------------------------------ Edit+------------------+-------------
| Line 1 Col 1 Insert Indent Ta| Compiler |DELC.C
|/* **************************************| +---------------------------+
|@@ DECL - A program for testing Decl| | Model Tiny |
|** **************************************| | Defines +---------+
| | | Code generation | Tiny |
|void main() | | Optimization | Small |
|{ | | Source | Medium |
| unsigned char c1; +-| Errors | Compact |
| signed char c2; | Names | Large |
| char c3; +------------------| Huge |
| +---------+
| unsigned short s1;
Заявим, что имеем математический сопроцессор:
Options | Compiler | Code generation | Floating point | 8087/80287
File Edit Run Compile Project Options Debug Break/watch
+------------------------------------ Edit+------------------+-----------------+
| Line 1 Col 1 Insert Indent Ta| Compiler |DELC.C |
|/* **************************************| +---------------------------+ |
|@@ DECL - A program for testing Decl| | Model Small | |
|** **************************************| | Defines | |
| | | Code generation | |
|void main() +--------------------------------------+|
|{ | Calling convention C ||
| unsigned char c1; | Instruction set 8088/8086 ||
| signed char c2; | Floating point 8087/80287 ||
Закажем линкеру детальную карту памяти:
Options | Linker | Map file | Detailed
File Edit Run Compile Project Options Debug Break/watch
+------------------------------------ Edit+------------------+-----------------+
| Line 1 Col 1 Insert Indent Ta| Compiler |DELC.C |
|/* **************************************| Linker |******** ** |
|@@ DECL - A program for testing Decl|+----------------------------------+|
|** **************************************|| Map file Detailed ||
Сохраним установки:
Options | Save options | Y
File Edit Run Compile Project Options Debug Break/watch
+------------------------------------ Edit+------------------+-----------------+
| Line 1 Col 1 Insert Indent Ta| Compiler |DELC.C |
|/* **************************************| Linker |******** ** |
|@@ DECL - A program for testing Decl| Environment | |
|** **************************************| Directories |******** */ |
| | Arguments | |
|void main() | Save options | |
|{ | +------------- Verify -------------+
| unsigned char c1; +-| Overwrite \TC\TCCONFIG.TC? (Y/N) |
| signed char c2; +----------------------------------+
Скомпилируем и выполним эту программу (CTRL-F9).
Как и следовало ожидать, ничего не случилось - ведь мы не предусмотрели в
программе ничего, кроме деклараций.
Изучим теперь выходные файлы компилятора. Их три, они имеют тоже самое
имя, что и программа DECL и расширения (extensions) .OBJ, .MAP и .EXE
DECL.MAP - это обычный текстовый файл, а .OBJ и .EXE - двоичные файлы, для
просмотра не предназначенные. Тем не менее, иногда бывает любопытно сунуть
нос и туда, где этого не ждут :-)
Начнем с DECL.OBJ - можете открыть его в любом HEX-редакторе или вьювере.
На самом деле, любителей поглядеть "А что у него внутри ..." так много,
что Borland поставляет со своими компиляторами специальную утилиту TDUMP,
для просмотра двоичных файлов и экстрагирования из них различной
информации. Ей я и воспользуюсь.
Turbo Dump Version 5.0.13.1 Copyright (c) 1988, 1997 Borland International
Display of File DELC.OBJ
000000: 80 08 00 06 44 45 4C 43 2E 43 E9 88 1E 00 00 00 ....DELC.C......
000010: 1A 54 43 38 36 20 42 6F 72 6C 61 6E 64 20 54 75 .TC86 Borland Tu
000020: 72 62 6F 20 43 20 32 2E 30 31 20 C9 88 0E 00 00 rbo C 2.01 .....
000030: E9 FB 04 2A 29 06 44 45 4C 43 2E 43 A0 88 06 00 ...*).DELC.C....
000040: 00 E5 01 00 00 8C 88 06 00 00 E5 01 03 00 89 88 ................
000050: 05 00 00 E7 05 00 87 88 05 00 00 E7 05 00 87 88 ................
000060: 03 00 00 E9 8C 88 05 00 00 EA 01 08 80 96 2F 00 ............../.
000070: 00 05 5F 54 45 58 54 04 43 4F 44 45 05 5F 44 41 .._TEXT.CODE._DA
000080: 54 41 04 44 41 54 41 04 5F 42 53 53 03 42 53 53 TA.DATA._BSS.BSS
000090: 06 44 47 52 4F 55 50 06 44 47 52 4F 55 50 F3 98 .DGROUP.DGROUP..
0000A0: 07 00 28 05 00 02 03 01 2E 98 07 00 48 00 00 04 ..(.........H...
0000B0: 05 01 0F 98 07 00 48 00 00 06 07 01 0B 9A 06 00 ......H.........
0000C0: 08 FF 02 FF 03 55 90 0C 00 00 01 05 5F 6D 61 69 .....U......_mai
0000D0: 6E 00 00 00 5A 88 0B 00 00 E3 18 00 00 00 23 01 n...Z.........#.
0000E0: 00 00 4E 88 05 00 00 E1 18 18 62 A0 09 00 01 00 ..N.......b.....
0000F0: 00 55 8B EC 5D C3 6A 88 0F 00 00 E8 00 06 44 45 .U..].j.......DE
000100: 4C 43 2E 43 FB 04 2A 29 A0 94 0B 00 00 01 05 00 LC.C..*)........
000110: 00 00 1A 00 03 00 3E 8A 02 00 00 74 00 00 00 00 ......>....t....
Гм. Любопытно. Фирма Borland описывает свой компилятор как TC86. Далее
следует версия компилятора: "Borland Turbo C 2.01" и всякий мусор, среди
которого мы можем разглядеть имена сегментов: _TEXT CODE _DATA DATA _BSS
BSS DGROUP и DGROUP.
Больше ничего интересного увидеть не удалось, перейдем к .EXE-файлу.
Поскольку большая часть его состоит либо из нулей, либо из двоичного
"мусора", я приведу только несколько фрагментов.
Turbo Dump Version 5.0.13.1 Copyright (c) 1988, 1997 Borland International
Display of File DELC.EXE
000000: 4D 5A 14 00 06 00 00 00 20 00 00 00 FF FF 00 00 MZ...... .......
000010: 00 00 00 00 00 01 00 00 22 00 00 00 01 00 FB 20 ........"......
000020: 72 6A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rj..............
000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Это стандартный заголовок EXE-файла. Вас возможно удивит, но точно также
он выглядит и в Win16 и Win32.
000840: 00 00 00 00 54 75 72 62 6F 2D 43 20 2D 20 43 6F ....Turbo-C - Co
000850: 70 79 72 69 67 68 74 20 28 63 29 20 31 39 38 38 pyright (c) 1988
000860: 20 42 6F 72 6C 61 6E 64 20 49 6E 74 6C 2E 00 44 Borland Intl..D
000870: 69 76 69 64 65 20 65 72 72 6F 72 0D 0A 41 62 6E ivide error..Abn
000880: 6F 72 6D 61 6C 20 70 72 6F 67 72 61 6D 20 74 65 ormal program te
000890: 72 6D 69 6E 61 74 69 6F 6E 0D 0A 00 00 00 00 00 rmination.......
Ничего интересного: версия компилятора, сообщения об ошибках ... Этот код
соответствует Runtime Library - исполняющей системе, код которой
подключается к Вашему на этапе линкования.
000E10: 00 00 00 00 00 00 00 00 5F 5F 65 78 69 74 00 5F ........__exit._
000E20: 5F 72 65 73 74 6F 72 65 7A 65 72 6F 00 5F 61 62 _restorezero._ab
000E30: 6F 72 74 00 44 47 52 4F 55 50 40 00 5F 6D 61 69 ort.DGROUP@._mai
000E40: 6E 00 5F 65 78 69 74 00 5F 5F 73 65 74 61 72 67 n._exit.__setarg
000E50: 76 00 5F 5F 73 65 74 65 6E 76 70 00 5F 61 74 65 v.__setenvp._ate
000E60: 78 69 74 00 5F 5F 5F 70 75 6C 6C 5F 66 72 65 65 xit.___pull_free
000E70: 5F 62 6C 6F 63 6B 00 5F 6D 61 6C 6C 6F 63 00 5F _block._malloc._
000E80: 5F 5F 62 72 6B 00 5F 5F 5F 73 62 72 6B 00 5F 62 __brk.___sbrk._b
000E90: 72 6B 00 5F 73 62 72 6B 00 5F 5F 49 6E 74 30 56 rk._sbrk.__Int0V
000EA0: 65 63 74 6F 72 00 5F 5F 49 6E 74 34 56 65 63 74 ector.__Int4Vect
000EB0: 6F 72 00 5F 5F 49 6E 74 35 56 65 63 74 6F 72 00 or.__Int5Vector.
000EC0: 5F 5F 49 6E 74 36 56 65 63 74 6F 72 00 5F 5F 61 __Int6Vector.__a
000ED0: 72 67 63 00 5F 5F 61 72 67 76 00 5F 65 6E 76 69 rgc.__argv._envi
000EE0: 72 6F 6E 00 5F 5F 65 6E 76 4C 6E 67 00 5F 5F 65 ron.__envLng.__e
000EF0: 6E 76 73 65 67 00 5F 5F 65 6E 76 53 69 7A 65 00 nvseg.__envSize.
000F00: 5F 5F 70 73 70 00 5F 5F 6F 73 6D 61 6A 6F 72 00 __psp.__osmajor.
000F10: 5F 5F 76 65 72 73 69 6F 6E 00 5F 5F 6F 73 6D 69 __version.__osmi
000F20: 6E 6F 72 00 5F 65 72 72 6E 6F 00 5F 5F 38 30 38 nor._errno.__808
000F30: 37 00 5F 5F 53 74 61 72 74 54 69 6D 65 00 5F 5F 7.__StartTime.__
000F40: 5F 68 65 61 70 62 61 73 65 00 5F 5F 5F 62 72 6B _heapbase.___brk
000F50: 6C 76 6C 00 5F 5F 5F 68 65 61 70 74 6F 70 00 5F lvl.___heaptop._
000F60: 5F 68 65 61 70 62 61 73 65 00 5F 5F 62 72 6B 6C _heapbase.__brkl
000F70: 76 6C 00 5F 5F 68 65 61 70 74 6F 70 00 65 6D 77 vl.__heaptop.emw
000F80: 73 5F 6C 69 6D 69 74 53 50 00 65 6D 77 73 5F 69 s_limitSP.emws_i
000F90: 6E 69 74 69 61 6C 53 50 00 65 6D 77 73 5F 73 61 nitialSP.emws_sa
000FA0: 76 65 56 65 63 74 6F 72 00 65 6D 77 73 5F 6E 6D veVector.emws_nm
000FB0: 69 56 65 63 74 6F 72 00 65 6D 77 73 5F 73 74 61 iVector.emws_sta
000FC0: 74 75 73 00 65 6D 77 73 5F 63 6F 6E 74 72 6F 6C tus.emws_control
000FD0: 00 65 6D 77 73 5F 54 4F 53 00 65 6D 77 73 5F 61 .emws_TOS.emws_a
000FE0: 64 6A 75 73 74 00 65 6D 77 73 5F 66 69 78 53 65 djust.emws_fixSe
000FF0: 67 00 65 6D 77 73 5F 42 50 73 61 66 65 00 65 6D g.emws_BPsafe.em
001000: 77 73 5F 73 74 61 6D 70 00 65 6D 77 73 5F 76 65 ws_stamp.emws_ve
001010: 72 73 69 6F 6E 00 5F 5F 65 78 69 74 62 75 66 00 rsion.__exitbuf.
001020: 5F 5F 65 78 69 74 66 6F 70 65 6E 00 5F 5F 65 78 __exitfopen.__ex
001030: 69 74 6F 70 65 6E 00 5F 5F 68 65 61 70 6C 65 6E itopen.__heaplen
001040: 00 5F 5F 73 74 6B 6C 65 6E 00 5F 5F 61 74 65 78 .__stklen.__atex
001050: 69 74 63 6E 74 00 5F 5F 52 65 61 6C 43 76 74 56 itcnt.__RealCvtV
001060: 65 63 74 6F 72 00 5F 5F 53 63 61 6E 54 6F 64 56 ector.__ScanTodV
001070: 65 63 74 6F 72 00 5F 5F 61 74 65 78 69 74 74 62 ector.__atexittb
001080: 6C 00 5F 5F 5F 6C 61 73 74 00 5F 5F 5F 72 6F 76 l.___last.___rov
001090: 65 72 00 5F 5F 5F 66 69 72 73 74 00 43 30 54 00 er.___first.C0T.
0010A0: 43 30 54 00 44 45 4C 43 2E 43 00 44 45 4C 43 00 C0T.DELC.C.DELC.
0010B0: 44 45 4C 43 2E 43 00 45 58 49 54 00 48 45 41 50 DELC.C.EXIT.HEAP
0010C0: 4C 45 4E 00 53 45 54 41 52 47 56 00 53 45 54 45 LEN.SETARGV.SETE
0010D0: 4E 56 50 00 53 54 4B 4C 45 4E 00 41 54 45 58 49 NVP.STKLEN.ATEXI
0010E0: 54 00 4D 41 4C 4C 4F 43 00 42 52 4B 00 00 00 00 T.MALLOC.BRK....
Полный список всех библиотечных функций. В более поздних версиях, Borland
стал снабжать свои компиляторы специальной утилитой TDSTRIP.EXE для
удаления отладочной информации из файла (это, кстати, существенно
уменьшает размер исполняемого модуля).
Well.
Для полного счастья нам не хватает только ассемблерного листинга. Получим
его используя TCC с ключом -S
> ifndef ??version
> ?debug macro
> endm
> endif
> ?debug S "delc.c"
> _TEXT segment byte public 'CODE'
> DGROUP group _DATA,_BSS
> assume cs:_TEXT,ds:DGROUP,ss:DGROUP
> _TEXT ends
> _DATA segment word public 'DATA'
> d@ label byte
> d@w label word
> _DATA ends
> _BSS segment word public 'BSS'
> b@ label byte
> b@w label word
> ?debug C E9FB042A290664656C632E63
> _BSS ends
> _TEXT segment byte public 'CODE'
> ; ?debug L 5
> _main proc near
> @1:
> ; ?debug L 26
> ret
> _main endp
> _TEXT ends
> ?debug C E9
> _DATA segment word public 'DATA'
> s@ label byte
> _DATA ends
> _TEXT segment byte public 'CODE'
> _TEXT ends
> public _main
> end
Гм. И что мы видим ? Назначения сегментов, метки для дебаггера и одну
единственную исполняемую команду: 'ret'.
А где же наши, столь тщательно описанные переменные ? Может быть в
сегменте данных ? Нет, их нет и там ... и нигде ...
Hell !
Что же стало со всеми нашими декларациями ?
А ничего. Компилятор их принял к сведению.
Поскольку никаких реальных действий с этими переменными не производилось,
то и никакого кода сгенерировано не было - информация о типе и именах
переменных была занесена во внутренние таблицы транслятора и исчезла с
окончанием компиляции.
Современные компиляторы выдают в таких случаях предупреждение об
описанной, но неиспользованной переменной.
Несколько слов о стиле деклараций.
Язык С позволяет свободную форму записи (немалое новшество в эпоху
Холлеритовских перфокарт), так что Вы можете записать всю программу в одну
строку или, наоборот, писать каждый идентификатор с новой строки.
Так вот, не делайте ни того, ни другого :-)
void main()
{ <-- Здесь начинается внешний блок
unsigned char c1; <-- Внутри блока все строки начинаются
signed char c2; с одним и тем же отступом (indent)
char c3;
Величина этого отступа также предмет для споров. Borland по умолчанию
использует 3, Microsoft - 4. Некоторые извращенцы - 2 или 5. С теми, кто
делает 1 или не делает вообще, просто не о чем разговаривать. Я всегда
буду использовать три пробела (и если Ваш редактор вставляет символы
табуляции - немедленно измените установки так, чтобы табуляция заменялась
на пробелы).
В языке С допускается одновременная декларация нескольких переменных
одного типа - списком. Например, так:
int x, y, z;
Никогда этого не делайте. Декларацию каждого идентификатора записывайте
отдельной строкой.
int x;
int y;
int z;
Такая запись не только легче читается и модифицируется, но и позволит Вам
избежать ошибок при объявлении указателей (мы еще поговорим об этом).
-----[05]----------[Homework]---------------------------------------------
В рабочей директории компилятора TC 2.0 на Вашем диске можно обнаружить
три файла с расширением .ASM (это комментированный исходный текст) и
директорию LIB, содержащую большое число объектных файлов. Разберитесь (с
помощью файла README) в их назначении и просто посмотрите "что у них
внутри". Выясните, какой библиотечный файл является источником тех
текстовых строк, которые Вы видите в дампе Вашей программы.
-----[06]----------[Info]-------------------------------------------------
Вопросы и замечания принимаются по адресу: aleph@canada.com
Предыдущие выпуски доступны со страницы архива:
http://www.subscribe.ru/archive/comp.prog.c4dummies/
или (в упакованном виде):
http://members.xoom.com/c4dummies/archive/000.zip
. . .
http://members.xoom.com/c4dummies/archive/010.zip
Рассылка дублируется (только текстовый вариант) с сервера www.egroups.com
Подписка: c4d-subscribe@egroups.com
-----[--]----------[The End]----------------------------------------------
© Gazlan 2009 * gazlan@yandex.ru
|