[go: up one dir, main page]

Menu

[r699]: / doc / index.html  Maximize  Restore  History

Download this file

1197 lines (926 with data), 47.8 kB

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252"></head><body style="margin-left: 50px; margin-right: 50px; margin-top: 30px; margin-bottom: 30px;"><p>
<title>The CMOC C-like 6809-targeting cross-compiler</title>
</p>
<h1>The CMOC C-like 6809-targeting cross-compiler</h1>
<p><strong>By Pierre Sarrazin</strong></p>
<p><code>sarrazip@sarrazip.com</code></p>
<p>Copyright © 2003-2016</p>
<p><a href="http://sarrazip.com/dev/cmoc.html">http://sarrazip.com/dev/cmoc.html</a></p>
<p>Distributed under the <strong>GNU General Public License</strong>,
<strong>version 3 or later</strong> (see the License section).</p>
<p>Version of CMOC covered by this manual: <strong>0.1.32</strong></p>
<p>Date of this manual: 2016-09-17</p>
<h2>Table of Contents</h2>
<small>
<ul>
<li><a href="#t1">Introduction</a></li> <!--2-->
<li><a href="#t2">Features</a></li> <!--2-->
<ul>
<li><a href="#t3">Unsupported features</a></li> <!--3-->
<li><a href="#t4">Supported C and C99 features</a></li> <!--3-->
</ul>
<li><a href="#t5">Differences with C</a></li> <!--2-->
<li><a href="#t6">Installing CMOC</a></li> <!--2-->
<ul>
<li><a href="#t7">The compiler</a></li> <!--3-->
</ul>
<li><a href="#t8">Running CMOC</a></li> <!--2-->
<ul>
<li><a href="#t9">Compiling a C program</a></li> <!--3-->
<li><a href="#t10">Disabling some optimizations</a></li> <!--3-->
<li><a href="#t11">Generated files</a></li> <!--3-->
<li><a href="#t12">The Motorola S-record (SREC) format</a></li> <!--3-->
<li><a href="#t13">The Vectrex video game console</a></li> <!--3-->
</ul>
<li><a href="#t14">Programming for CMOC</a></li> <!--2-->
<ul>
<li><a href="#t15">Signedness of integers</a></li> <!--3-->
<li><a href="#t16">Pre-increment vs. post-increment</a></li> <!--3-->
<li><a href="#t17">Origin address</a></li> <!--3-->
<li><a href="#t18">End address and length of the executable</a></li> <!--3-->
<li><a href="#t19">Enforcing a limit address on the end of the program</a></li> <!--3-->
<li><a href="#t20">Position-independent code</a></li> <!--3-->
<li><a href="#t21">Targeting CoCo Disk Basic or the USim 6809 simulator</a></li> <!--3-->
<li><a href="#t22">The standard library</a></li> <!--3-->
<ul>
<li><a href="#t23">Size of the standard library</a></li> <!--4-->
<li><a href="#t24">printf()</a></li> <!--4-->
<li><a href="#t25">Redirecting the output of printf()</a></li> <!--4-->
<li><a href="#t26">sprintf()</a></li> <!--4-->
<li><a href="#t27">Redefining a standard library function</a></li> <!--4-->
<li><a href="#t28">Dynamic memory allocation with sbrk()</a></li> <!--4-->
</ul>
<li><a href="#t29">Inline assembly</a></li> <!--3-->
<ul>
<li><a href="#t30">Preprocessor identifiers in inline assembly</a></li> <!--4-->
<li><a href="#t31">Referring to variables whose name is that of a register</a></li> <!--4-->
<li><a href="#t32">Assembly-only functions</a></li> <!--4-->
<li><a href="#t33">Functions that are only called by assembly code</a></li> <!--4-->
</ul>
<li><a href="#t34">Interrupt Service Routines</a></li> <!--3-->
<li><a href="#t35">Function pointers</a></li> <!--3-->
<li><a href="#t36">Array initializers</a></li> <!--3-->
<ul>
<li><a href="#t37">Local vs. global array</a></li> <!--4-->
<li><a href="#t38">Execution of global array initializers</a></li> <!--4-->
</ul>
<li><a href="#t39">Enumerations (enum)</a></li> <!--3-->
<li><a href="#t40">Compiling a ROM image for a cartridge</a></li> <!--3-->
<li><a href="#t41">Detecting null pointer accesses at run time</a></li> <!--3-->
<li><a href="#t42">Detecting stack overflows at run time</a></li> <!--3-->
<li><a href="#t43">Single-execution programs</a></li> <!--3-->
<li><a href="#t44">Calling convention</a></li> <!--3-->
<li><a href="#t45">Compiling a program executable by the DOS command</a></li> <!--3-->
<li><a href="#t46">Unused functions</a></li> <!--3-->
</ul>
<li><a href="#t47">License</a></li> <!--2-->
</ul>
</small>
<h2><a name="t1"></a>Introduction</h2>
<p>CMOC is a <a href="https://en.wikipedia.org/wiki/Unix">Unix</a>-based program that
compiles a <a href="https://en.wikipedia.org/wiki/C_%28programming_language%29">C</a>-like
language, generates <a href="https://en.wikipedia.org/wiki/Motorola_6809">Motorola 6809</a>
assembly language programs and assembles them into executables for the
<a href="https://en.wikipedia.org/wiki/TRS-80_Color_Computer">Color Computer</a>'s
Disk Basic environment. (As of version 0.1.18, targeting the
<a href="https://en.wikipedia.org/wiki/Vectrex">Vectrex</a> video game console
is also supported.)</p>
<p>CMOC is not meant to be able to compile existing C programs.
It is a tool to develop new programs for the Color Computer (CoCo).</p>
<p>The efficiency of the generated machine language is modest,
but the resulting machine language will be faster
than the equivalent interpreted
<a href="https://en.wikipedia.org/wiki/Color_BASIC">Color Basic</a> program.
This was the initial goal of the CMOC project.</p>
<p>The main features missing from C are longs, floats, const and
separate compilation.</p>
<p>CMOC itself is written in <a href="https://en.wikipedia.org/wiki/C%2B%2B">C++</a>
for a Unix-like system. The C++ source code is somewhat complicated
because of the anarchic development process that gave rise to CMOC.
Years ago, development was able to take off because having a working
product had higher priority than having a clean but theoretical design.</p>
<h2><a name="t2"></a>Features</h2>
<h3><a name="t3"></a>Unsupported features</h3>
<ul>
<li><p><a href="https://en.wikipedia.org/wiki/Floating_point">Floating-point</a> arithmetic
(no float or double types).</p></li>
<li><p>32-bit arithmetic (no long type). Type char is 8 bits and short and int are 16 bits.</p></li>
<li><p>The const keyword.</p></li>
<li><p>Separate compilation (i.e., compiling several source files
to several object files that get linked together).</p></li>
<li><p>Bit fields.</p></li>
<li><p>Type-safe function pointers.
(The address of a function has type <code>void *</code>
and the return type of a call through a pointer is assumed to be int.)</p></li>
<li><p>Typedefs local to a function (global typedefs are supported).</p></li>
<li><p>Structs local to a function (global structs are supported).</p></li>
<li><p>Indirection of a pointer to a <em>struct</em> used as an r-value (e.g., <code>*ptr</code> alone).
The l-value case is supported, e.g., <code>(*ptr).field</code>.</p></li>
<li><p>Passing a struct by value to a function.</p></li>
<li><p>Comma expressions (e.g., x = 1, y = 2, z = 3;).</p></li>
<li><p>register, extern, static, volatile. The register keyword is accepted but ignored.</p></li>
<li><p><a href="https://en.wikipedia.org/wiki/C_%28programming_language%29#K.26R_C">K&amp;R</a>
function definitions, i.e., f() int a; { ... }</p></li>
<li><p>A continue statement in a switch() body.</p></li>
<li><p>Implementing <a href="https://en.wikipedia.org/wiki/Duff%27s_device">Duff's device</a>
in a switch().</p></li>
<li><p>Function-local <a href="https://en.wikipedia.org/wiki/Function_prototype">function prototypes</a>.
All prototypes must be declared at global scope.</p></li>
<li><p>Zero-element arrays.</p></li>
</ul>
<h3><a name="t4"></a>Supported C and C99 features</h3>
<ul>
<li><p>Pointers, including pointers to pointers, etc.</p></li>
<li><p>Structs, including a struct in a struct. Struct initializers.
A struct must be declared at the global level.
A reference to an undefined struct is accepted if the declaration
or statement only refers to a pointer to such a struct.</p></li>
<li><p>Anonymous structs.</p></li>
<li><p>Assigning a struct value to another (e.g., <code>struct S a, b; a = b;</code>).
Initializing a struct from another one is also supported (e.g.,
<code>struct S a; struct S b = a;</code>).</p></li>
<li><p>char (8 bits), int (16 bits), signed, unsigned, typedef (global only).
A function's return type can be void.</p></li>
<li><p>Declaring a variable in the middle of a function, as in
<a href="https://en.wikipedia.org/wiki/C99">C99</a>.</p></li>
<li><p>while, do, for, switch, continue, break.</p></li>
<li><p>Declaring a for() loop's control variable in the for() itself as in C99,
i.e., for (int i = 0; ...) {}.</p></li>
<li><p>Declaring more than one variable on the same line, i.e., int a = 0, b = 1;</p></li>
<li><p><a href="https://en.wikipedia.org/wiki/Variadic_function">Variadic functions</a>,
i.e., void foo(const char *format, ...). There must be at least one named
argument before the ellipsis (...), as in ISO C.</p></li>
<li><p>Ending an initializer list with a comma.</p></li>
<li><p>Use of the <a href="https://en.wikipedia.org/wiki/C_preprocessor">C preprocessor</a>
(the system's cpp is invoked): #include, #define, #ifdef, etc.
(Use #includes instead of separating the program in more than one .c file.)</p></li>
<li><p>Unions (since version 0.1.12).</p></li>
<li><p>Enumerations (since version 0.1.29).</p></li>
<li><p>Generating <a href="https://en.wikipedia.org/wiki/OS-9">OS-9</a> executables (since
version 0.1.15, using the <code>--os9</code> command-line option).</p></li>
<li><p><a href="https://en.wikipedia.org/wiki/Goto">Goto</a> and non-case labeled statements.</p></li>
</ul>
<h2><a name="t5"></a>Differences with C</h2>
<p>CMOC is sometimes more strict than C on some points.
For instance, it is an error to call an undeclared function.</p>
<p>If a large discrepancy exists between C and CMOC,
a bug report should be filed.</p>
<h2><a name="t6"></a>Installing CMOC</h2>
<p>The following instructions assume a Unix-like system.
A C++ compiler is necessary to compile CMOC.</p>
<h3><a name="t7"></a>The compiler</h3>
<p>Deploy the .tar.gz source archive in a directory, go to this directory,
read the generic installation instructions in the INSTALL file, then (typically)
give these commands:</p>
<blockquote>
<p>tar -xzf cmoc-0.1.XX.tar.gz</p>
<p>cd cmoc-0.1.XX</p>
<p>./configure --prefix=/some/installation/dir</p>
<p>make</p>
<p>make install</p>
</blockquote>
<p>The sudo prefix may be needed to do a <code>make install</code>
to a system directory like /usr/local/bin.</p>
<p>The "check" makefile target runs several unit tests.</p>
<p>The compiler executable is called "cmoc".</p>
<p>To generate the HTML documentation (this document), do <code>make html</code>, which
will create the file <code>doc/cmoc-manual.html</code>.</p>
<h2><a name="t8"></a>Running CMOC</h2>
<h3><a name="t9"></a>Compiling a C program</h3>
<p>The following must be in the path:</p>
<ul>
<li><p>A C preprocessor callable by the name "cpp".</p></li>
<li><p>The <a href="http://lwtools.projects.l-w.ca/">LWTOOLS</a> lwasm assembler.</p></li>
</ul>
<p>To compile a program written in the file foo.c, run this command:</p>
<blockquote>
<p>cmoc foo.c</p>
</blockquote>
<p>By default, the resulting .bin file will load at address $2800 on a CoCo
(see the <code>#pragma org</code> directive elsewhere in this manual).
The generated machine language is position-independent, so the .bin file
can be loaded with an offset, by passing a second argument to Disk Basic's
LOADM command.</p>
<p>Pass <code>--help</code> to cmoc to see the available options.</p>
<p>CMOC comes with a <code>writecocofile</code> command that can copy a .bin file
to a 35-track Disk Basic diskette image file. For example:</p>
<blockquote>
<p>writecocofile testing.dsk foo.bin</p>
</blockquote>
<p>Pass <code>--help</code> to writecocofile for more options.</p>
<p>For more information on running a CoCo emulator on a GNU/Linux system, see
<a href="http://sarrazip.com/emul-coco.html">http://sarrazip.com/emul-coco.html</a>.</p>
<h3><a name="t10"></a>Disabling some optimizations</h3>
<p>By default, all peephole optimizations are enabled.</p>
<p>The <a href="https://en.wikipedia.org/wiki/Peephole_optimization">peephole optimizer</a>
can be disabled by passing the <code>-O0</code> option to the compiler.
This can be useful when one suspects that the compiler may have generated
invalid code.</p>
<p>Several peephole optimizations were contributed by Jamie Cho in early 2016
for version 0.1.20. They can be disabled by passing <code>-O1</code>.</p>
<p>Option <code>-O2</code> is equivalent to using the default (full) optimization level.</p>
<h3><a name="t11"></a>Generated files</h3>
<p>From the .c file passed to <code>cmoc</code>, the compiler generates these files:</p>
<ul>
<li><p><strong>.asm</strong>: The assembler file written by CMOC. It contains <code>#include</code>
statements that refer to stdlib.inc and stdlib-data.inc, which are
typically installed in /usr/share/cmoc, or elsewhere depending
on the installation prefix given to the <code>configure</code> script.</p></li>
<li><p><strong>.i</strong>: The .asm file as processed by the C preprocessor (cpp), using
the include directories and defines passed to the <code>a09</code> assembler script.
This file contains pure assembly, without #include statements or comments.</p></li>
<li><p><strong>.lst</strong>: The listing generated by the 6809 assembler (lwasm).
This is useful to see exactly where the code and data end up in memory.</p></li>
<li><p><strong>.hex</strong>: The executable program in
<a href="http://en.wikipedia.org/wiki/Intel_HEX">Intel HEX format</a>.
This format is understood by the usim 6809 simulator that is used
by the <code>make check</code> test suite.</p></li>
<li><p><strong>.bin</strong>: The executable in Disk Basic .bin format. This can be
transfered to a CoCo or emulator and loaded with the LOADM command.
(If compiling for OS-9—with the <code>--os9</code> command-line switch—the
executable has the name of the C file without the extension.)</p></li>
</ul>
<p>When distributing the .bin file to CoCo users, it is not
necessary or useful to accompany it with the other generated files.</p>
<h3><a name="t12"></a>The Motorola S-record (SREC) format</h3>
<p>Pass the <code>--srec</code> option to cmoc to make
it generate an executable in
<a href="https://en.wikipedia.org/wiki/SREC_%28file_format%29">Motorola S-record format</a>.
The additional file will have the .srec extension.</p>
<h3><a name="t13"></a>The Vectrex video game console</h3>
<p>The doc subdirectory of the source distribution contains
cmoc-vectrex.markdown, which gives Vectrex-specific instructions.
Giving the <code>make html</code> command will generate cmoc-vectrex.html,
which can be viewed in a browser.</p>
<p>Note that questions regarding Vectrex-specific issues should be
addressed to <strong>Johan Van den Brande</strong> at <code>johan@vandenbrande.com</code>.</p>
<h2><a name="t14"></a>Programming for CMOC</h2>
<h3><a name="t15"></a>Signedness of integers</h3>
<p>The compiler generally produces more efficient code for unsigned
arithmetic. Therefore, types <code>unsigned</code> and <code>unsigned char</code> should
be preferred to <code>int</code> and <code>char</code> where possible.</p>
<p>CMOC considers that the signedness of an additive of multiplicative
operation is the signedness of the left operand.</p>
<h3><a name="t16"></a>Pre-increment vs. post-increment</h3>
<p>The pre-increment (++i) typically generates one instruction less
than the post-increment (i++). This is because the post-increment
must yield the <em>initial</em> value of the variable. When this initial
value is not needed, it is advisable to use the pre-increment.</p>
<p>The same situation holds for the decrement operators.</p>
<h3><a name="t17"></a>Origin address</h3>
<p>To specify the origin address of the program, start your program with a
<code>#pragma org</code> directive. For example:</p>
<blockquote>
<p>#pragma org 0x5C00</p>
</blockquote>
<p>By default, the origin address is 0x2800. (Under Disk Basic, the
Basic program normally starts at 0x2601, because four PMODE pages
are reserved by default.)</p>
<h3><a name="t18"></a>End address and length of the executable</h3>
<p>To determine the effective start and end address of the executable
(assuming no relocation by LOADM), one can look up the <code>program_start</code>
and <code>program_end</code> symbols in the .lst listing file generated by the
assembler.</p>
<p><code>program_end</code> is useful to check that the executable fits in the
available RAM. On a 32k CoCo, the RAM ends at $8000. By defaut,
Color Basic reserves 200 bytes for Basic strings, and before that,
the system stack should be given 512 bytes for a typical C program.
These assumptions mean that an executable should not go beyond $7D38.</p>
<p><strong>If a program crashes the CoCo just by getting loaded</strong>, it could
be because it is too long and overwrites the system stack. The
<code>parse-coco-bin</code> Perl script, available on the CMOC home page,
can be useful to confirm that.</p>
<p>The following example program prints the start and end of the memory
it uses initially:</p>
<pre><code>#include &lt;cmoc.h&gt;
int main()
{
char *s, *e;
asm
{
leax program_start,pcr
stx s
leax program_end,pcr
stx e
}
printf("START AT %p, END AT %p.\n", s, e);
return 0;
}
</code></pre>
<p>Note that the label addresses are taken relatively to the
program counter (<code>,pcr</code>), so that this program will report
the correct addresses even if the program is loaded at an
address other than the one specified in the .bin file.
(This can be done by passing a second argument to Disk Basic's
LOADM command.)</p>
<p>This section assumes that the code and data sections form a single
block. When using the <code>#pragma data</code> directive (see elsewhere
in this manual), the <em>writable</em> globals will not be between
<code>program_start</code> and <code>program_end</code>.</p>
<p>As of version 0.1.20, CMOC automatically displays the program start
and end addresses, as well as the start and end of the writable data
section, when the <code>--verbose</code> option is passed. In the following
example, <code>#pragma org</code> and <code>data</code> have been used to position the
code and data separately:</p>
<pre><code>Notable addresses:
program_start $C000
program_end $DC39
writable_globals_start $3800
writable_globals_end $3B7A
</code></pre>
<h3><a name="t19"></a>Enforcing a limit address on the end of the program</h3>
<p>As of version 0.1.20, CMOC accepts the <code>--limit=X</code> option. When it
is passed, CMOC will fail if the end of the program, as indicated
by the <code>program_end</code> listing symbol, exceeds address X (specified
in hexadecimal).</p>
<p>For example, <code>--limit=7800</code> will keep the program from finishing
too close to the system stack under Disk Basic, which is not far
below $8000. A limit at $7800 leaves two kilobytes for the stack
and for Basic's string space.</p>
<p>It is not necessary to pass the <code>--verbose</code> option to use the
<code>--limit</code> option.</p>
<h3><a name="t20"></a>Position-independent code</h3>
<p>All 6809 code generated by CMOC is position-independent, i.e.,
it can be loaded at any address and will still work.</p>
<h3><a name="t21"></a>Targeting CoCo Disk Basic or the USim 6809 simulator</h3>
<p>By default, the compiler defines the <code>_COCO_BASIC_</code> preprocessor
identifier. This identifier can be used to adapt a program to
make it use alternative code depending on whether it will run under
Disk Extended Color Basic or not.</p>
<p>By passing the <code>--usim</code> option, the compiler will target the USim
6809 simulator, which comes with CMOC. No .bin file is produced
in this case. The .hex file can be executed by passing its name to
<code>src/usim-0.91-cmoc/usim</code>.</p>
<h3><a name="t22"></a>The standard library</h3>
<p>CMOC's standard library is small. The program must <code>#include &lt;cmoc.h&gt;</code>
to use functions like printf(). See that file for a list of implemented C functions.
Most are standard C functions while others are CMOC extensions.</p>
<p>dwtoa(), meaning "double word to ASCII", is not a standard C function.
It takes an 11-character buffer and two
unsigned integers. It converts the 32-bit value formed by these integers into
an ASCII decimal represented stored in the buffer. The address of the first
character of this decimal string is returned. For example, this code returns a pointer
to a string equal to "65536".</p>
<pre><code>char buf[11];
char *p = dwtoa(buf, 1, 0);
</code></pre>
<p>readline() acts like Basic's LINE INPUT command and returns the address of
the string entered.</p>
<p>Each assembly program generated by CMOC includes stdlib.inc, which assembles
to about 2000 bytes of machine code. In the future, a mechanism could be implemented
in the compiler to reduce this overhead. In the mean time, one can remove the
unneeded parts of this file, if memory is at a premium.</p>
<h4><a name="t23"></a>Size of the standard library</h4>
<p>As of version 0.1.9, the standard library takes up almost 2048
bytes when all of its functions are called by the program.</p>
<p>But as of that version, only the standard library functions that
are actually called are included in the final assembly program.</p>
<p>A program that calls none of these functions will shed about 2000
of those bytes.</p>
<h4><a name="t24"></a>printf()</h4>
<p>CMOC's printf() function supports %u, %d, %x, %X, %p, %s,
%c and %%. Specifying a field width is allowed, but
a left justification is only supported for strings, i.e.,
<code>%-15s</code> will work, but <code>%-6u</code> will not.
Zero padding for a number is supported (e.g., <code>%04x</code>).</p>
<p>%p always precedes the hexadecimal digits with <code>$</code>, as per
the CoCo assembly language notation. %x and %X do not generate
such a prefix. %p, %x and %X always print letter digits as
capital letters (A to F, not a to f).</p>
<p>printf(), like putchar() and putstr(), sends its output one
character at a time to Color Basic's PUTCHR routine, whose
address is taken from $A002.</p>
<h4><a name="t25"></a>Redirecting the output of printf()</h4>
<p>The standard library's printf() writes the characters of the formatted
string by calling the routine whose address is stored in the library's
CHROUT global variable (not to be confused with Color Basic's CHROUT
vector at $A002).
The same applies to functions sprintf(), putchar() and putstr().</p>
<p>By default, under Color Basic,
that routine is the one found in that $A002 vector.
To designate a C function as the new character output routine,
first define the new routine:</p>
<pre><code>void newOutputRoutine()
{
char ch;
asm
{
pshs x,b // preserve registers used by this routine
sta ch
}
// Insert C statements that print or otherwise process 'ch'.
asm
{
puls b,x
}
}
</code></pre>
<p>This routine will receive the character to be printed in register A.
It <strong>must</strong> preserve registers B, X, Y and U.
It does not have to preserve A.</p>
<p>Install it at the appropriate time with this call:</p>
<pre><code>void *oldCHROOT;
oldCHROOT = setConsoleOutHook(newOutputRoutine).
</code></pre>
<p>To restore the original output routine, do this:</p>
<pre><code>setConsoleOutHook(oldCHROOT);
</code></pre>
<h4><a name="t26"></a>sprintf()</h4>
<p>This function is like printf(), but it writes into a memory buffer
whose address is passed as the first argument, before the format string.
For example:</p>
<pre><code>char greeting[32];
void f(char *name)
{
sprintf(greeting, "Hello, %s.", name);
}
</code></pre>
<p>Calling f("Lonnie") will write "Hello, Lonnie." in the greeting[] array,
including a terminating '\0' character. A total of 15 bytes
get written to the start of that array. </p>
<p>The <strong>caller is responsible for providing a buffer long enough</strong> to
receive all the text resulting from the format string and its arguments,
<em>including the terminating '\0' character</em>.</p>
<p>In this example, the longest "name" that can be safely passed to f()
would be a 23-character name.</p>
<p>The standard C language offers snprintf(), which is safer because it requires
passing the length of the destination buffer. But checking for
this limit would have a performance hit that is not necessarily
acceptable on a CoCo. If such a function is needed, it can be
implemented using the technique described in the previous section.</p>
<h4><a name="t27"></a>Redefining a standard library function</h4>
<p>Defining a function using the name of a standard library function
is allowed. For example, a program could redefine <code>rand()</code> and
<code>srand()</code> to implement an alternative random number generator.
In the final assembly program, such functions replace the ones
provided by the standard library.</p>
<h4><a name="t28"></a>Dynamic memory allocation with sbrk()</h4>
<p>sbrk() is a function that dynamically allocates a region of memory
of the size (in bytes) passed to it as an argument. It returns a
void pointer. If the quantity of memory requested is not available,
sbrk() returns <code>(void *) -1</code>. For example:</p>
<pre><code>void *p = sbrk(100);
if (p != (void *) -1)
memset(p, 'X', 100);
</code></pre>
<p>The name of the function comes from the notion of a "program break",
which is the current end of the memory allocated to the program.
The memory after that is presumed to be free for dynamic allocation.</p>
<p>In the case of the CoCo, the assumption is that the program is loaded
after the Basic program and variables. This means the space that
sbrk() can allocate from goes from there to the top of the stack,
which is around $3F00 on a 16K CoCo and $7F00 on a 32K-or-more CoCo.</p>
<p>To determine how much of that memory is available for sbrk(),
call sbrkmax(), which returns the number of bytes as a size_t
(unsigned). CMOC ends the region available to sbrk() about 1024 bytes
before the stack pointer, leaving those bytes to program calls and
local variables.</p>
<p>sbrkmax() returns 0 if the program is loaded after the stack space.</p>
<p>Be careful when using both sbrk() and #pragma const_data (see
previous section). If the data is not positioned correctly, sbrk()
calls may end up allocating memory that is used by some global
variables.</p>
<h3><a name="t29"></a>Inline assembly</h3>
<p>Inline assembly text can be specified by surrouding it with <code>asm {</code>
and <code>}</code>. In the text, one can refer to C variables (global, local
and parameters) as well as functions.
Labels can be used
for branch instructions, but a label must either be unique to the whole program
or comply with what lwasm considers a "local" label.
Prefixing a global label with the name of the current C function is a
good way to help prevent clashes. A label must appear at the
very beginning of the line, without spaces or tabs in front of it.</p>
<p>One way of using lwasm <strong>local labels</strong> is to prefix the label name with
the @ character. Such a label will be local to the current block, which
will begin at the previous blank line (or start of the <code>asm</code> block) and
end at the next blank line (or end of the <code>asm</code> block). Refer to the
<a href="http://lwtools.projects.l-w.ca/manual/manual.html#AEN237">LWASM manual about its symbols</a>
for details on using local labels.</p>
<p>The following example fills array <code>out</code> with <code>n</code> copies of character <code>ch</code>,
then returns the address that follows the region written to:</p>
<pre><code>#include &lt;cmoc.h&gt;
char *f(char *out, char ch, unsigned char n)
{
char *end;
asm
{
ldx out /* comments must be C style */
lda ch // or C++ style
ldb n
f_loop:
sta ,x+
decb
bne f_loop
stx end
}
return end;
}
int main()
{
char a[10];
a[9] = '\0';
char *p = f(a, 'X', (unsigned char) sizeof(a) - 1);
printf("a='%s', %p, %p\n", a, a, p);
return 0;
}
</code></pre>
<p>Since version 0.1.21, when referring to a C function, the function
name is replaced with its assembly label, possibly followed by the
<code>,pcr</code> suffix. This suffix is omitted if the instruction is BSR,
LBSR or JSR, because these instructions do not support the <code>,pcr</code> suffix and
they do not need it anyway. The following example calls the same C
function three different ways:</p>
<pre><code>asm
{
jsr someCFunction
lbsr someCFunction
leax someCFunction
jsr ,x
}
</code></pre>
<p>Note that CMOC always generates position independent code. This rule
should be maintained in inline assembly if the resulting program is to
be relocatable.</p>
<p>The BSR instruction is not recommended because it is a short branch
and if the called function is too far from the call, the assembly
step will fail.</p>
<h4><a name="t30"></a>Preprocessor identifiers in inline assembly</h4>
<p>The GNU C preprocessor can add spaces in surprising ways, which makes its
use slightly problematic in inline assembly. For example:</p>
<pre><code>#define PIA0 0xFF00
asm
{
stb PIA0+2
}
</code></pre>
<p>One would expect this code to generate an <code>stb 0xFF02</code> instruction,
but cpp will actually expand this to <code>stb 0xFF00 +2</code>, because it
apparently adds a space after the expansion of the PIA0 identifier.</p>
<p>lwasm takes this space as the start of the comment, so it ignores
the +2 and assembles <code>stb $FF00</code>.</p>
<p>A workaround appears to be reverse the addition and write <code>stb 2+PIA0</code>.
No space gets added before the identifier.</p>
<p>Therefore, preprocessor identifiers should be used with caution in
inline assembly.</p>
<h4><a name="t31"></a>Referring to variables whose name is that of a register</h4>
<p>Before version 0.1.31, bad assembly language text could be emitted
if inline assembly referred to a C variable that has the name of a
register. To help resolve this ambiguity, version 0.1.31 introduced
a <em>C variable escape character</em>, which is a colon that is put in
front of the C variable name.</p>
<p>For example:</p>
<pre><code>char b;
asm
{
inc :b
ldb :b
leax b,x
}
</code></pre>
<p>Here, <code>:b</code> refers to variable <em>b</em> of the C program, while the <em>b</em>
in <em>b,x</em> refers to the register.</p>
<p>This change may break inline assembly code in programs that were
written for versions of CMOC preceding 0.1.31. Adding a colon at
the right places will resolve the issue.</p>
<p>Note that the escape character is not necessary on variable names
that are not also register names.</p>
<h4><a name="t32"></a>Assembly-only functions</h4>
<p>When a function is written entirely in assembly language for
performance reasons, the stack frame may not be necessary.
CMOC will not generate a stack frame for a function defined
with the <code>asm</code> modifier, as in this example:</p>
<pre><code>asm int f(int m, int n)
{
// U not pushed, so 1st argument is at 2,s
asm
{
ldd 2,s // load m
addd 4,s // add n, leave return value in D
}
}
</code></pre>
<p>Only <code>asm { ... }</code> statements are allowed in such a function.
Typically, only one is needed. Local variables cannot be defined
in that function and the function's parameters cannot be accessed
by name. The assembly code is allowed to refer to global
variables however.</p>
<p>CMOC still ends the function with the RTS instruction
(or RTI if the function is declared with the <code>interrupt</code> modifier.)</p>
<p>See the <em>Calling convention</em> section elsewhere in this manual
for the rules to observe. In particular, note that byte arguments
are promoted to words, which are pushed onto the stack in the big
endian byte ordering.</p>
<h4><a name="t33"></a>Functions that are only called by assembly code</h4>
<p>Normally, CMOC does not emit code for a function that is never
called and whose address is never taken. But such a function
could still be called by inline assembly. This can lead to an
assembler error that complains that the LBSR or JSR argument
is not defined.</p>
<p>CMOC can be forced to emit all functions by passing it the
<code>--emit-uncalled</code> option.</p>
<h3><a name="t34"></a>Interrupt Service Routines</h3>
<p>CMOC supports the <code>interrupt</code> function modifier, which tells the
compiler to end the function with an RTI instruction instead of
an RTS. For example:</p>
<pre><code>interrupt void newCoCoIRQRoutine()
{
asm
{
lda $FF03 // check for 60 Hz interrupt
bpl irqISR_end // return if 63.5 us interrupt
lda $FF02 // reset PIA0, port B interrupt flag
}
// Do something in C.
asm
{
irqISR_end:
}
// Nothing here, so that next instruction is RTI.
}
</code></pre>
<h3><a name="t35"></a>Function pointers</h3>
<p>The address of a function can be taken and stored in order to be
called through that pointer later. However, unlike in the C language,
a CMOC function pointer expression always has type <code>void *</code>.</p>
<p>This means that function pointers are not type-safe with CMOC.</p>
<p>The following example shows that the two syntaxes used in C to call
a function through a pointer are supported by CMOC:</p>
<pre><code>unsigned char f(int a, char b) { ... }
int main()
{
void *pf = f;
unsigned char c0 = (unsigned char) (*pf)(1000, 'x');
unsigned char c1 = (unsigned char) pf(1001, 'y');
return 0;
}
</code></pre>
<p>Because CMOC does not know the return type of such a call, it is
important to cast it to the exact type returned by the function
that is actually called.</p>
<p>A member of a struct can point to a function. For example:</p>
<pre><code>struct S
{
void *fp;
};
void g() { ... }
int main()
{
struct S s = { g }; // member 'fp' points to g()
s.fp(); // call g()
return 0;
}
</code></pre>
<p>Since version 0.1.28, CMOC supports the full function pointer
notation, e.g., <code>int (*pf)(char, int *, char[])</code>, but the
effective type of such a pointer is still <code>void *</code>. This full
notation can be used to declare a variable but also a function
parameter.</p>
<h3><a name="t36"></a>Array initializers</h3>
<h4><a name="t37"></a>Local vs. global array</h4>
<p>When only a single function needs to use a read-only array of
integers, this array could be defined locally to that function,
but it is more efficient, as of CMOC 0.1.10 to define the array as
global. This is because the global array will be emitted as a
sequence of FCB or FDB directives, while a local array will be
initialized with a series of load and store instructions.</p>
<p>In the following example, array <code>g</code> will be initialized more
efficiently than array <code>l</code>:</p>
<pre><code>int g[] = { 55, 66, 77 };
void f()
{
int l[] = { 22, 33, 44 };
/* ... */
}
</code></pre>
<h4><a name="t38"></a>Execution of global array initializers</h4>
<p>A global array initializer containing only integer values (not
string literals) is treated specially. It is initialized
at compile-time, not at run-time. This means that if the program
modifies the array, quits, and then is reexecuted, the modified
contents will still appear as is. The array will not be reinitialized
to the values in the initializer.</p>
<p>For example:</p>
<pre><code>int a[2] = { 13, 17 };
int main() { a[0]++; printf("%d\n", a[0]); }
</code></pre>
<p>The first time this program is executed, a[0] starts at 13,
it is incremented to 14, which is the number that is printed.</p>
<p>The second time this program is executed, a[0] starts at 14
because array <code>a</code> is <em>not</em> reinitialized upon entry.</p>
<p>This is meant to save memory by not including a second copy
of the initializer just for run-time initialization purposes.</p>
<h3><a name="t39"></a>Enumerations (enum)</h3>
<p>Enumerations are supported, with the restriction that an enum must
be declared at the global scope. In particular, an enum with an
enumerator list (e.g., <code>enum { A, B }</code>) cannot be used in the formal
parameter of a function, nor as its return type.</p>
<p>An enum can be anonymous (e.g., <code>enum { A, B }</code>) or be given a name
(e.g., <code>enum E { A, B }</code>).</p>
<p>Each enumerated name can have a specified value, e.g.,
<code>enum { SCREEN = 0x0400, BIT5 = 1 &lt;&lt; 5 }</code>. Such a value must be
a constant expression.</p>
<h3><a name="t40"></a>Compiling a ROM image for a cartridge</h3>
<p>To help support the ROM cartridge format, CMOC supports directives
that allow telling it to assemble the code, the string literals
and the read-only global variables at the typical cartridge ROM
address of $C000, while mapping the writable global variables
at a RAM address like $3800.</p>
<p>This is achieved by using the four #pragma directives that
appear in this example:</p>
<pre><code>#pragma org $C000
#pragma data $3800
int f() { return 42; }
int writableGlobal = f();
#pragma const_data start
int readOnlyGlobal = 100;
unsigned char byteArray[3] = { 11, 22, 33 };
char text[] = "hello";
#pragma const_data end
int anotherWritableGlobal;
int main()
{
anotherWritableGlobal = 99;
return 0;
}
</code></pre>
<p>Note that <code>writableGlobal</code> is allowed to have a run-time initializer
because it is writable.</p>
<p><code>readOnlyGlobal</code>, <code>byteArray</code> and <code>text</code> are read-only because they appear
between the <code>const_data</code> directives. More than one such section can
appear in the same program.</p>
<p>In the case of <code>text</code>, the use of the empty brackets is necessary:
declaring text as <code>char *text</code> would be rejected by CMOC.
This is because <code>text</code> would then be a pointer whose initialization
would have to be at run-time, because the address of a string literal
depends on where the program is loaded by the user.</p>
<p><code>anotherWritableGlobal</code> is writable because it is not in a <code>const_data</code>
section. It is allowed to have no initializer because it is writable.</p>
<p>Using sbrk() can be dangerous depending on where in memory the
writable data section is positioned.</p>
<p>After compiling the program, the .bin file normally contains
a single contiguous block of code. Extract this block with
this Perl command:</p>
<pre><code>perl -e 'sysread(STDIN,$h,5)==5 or die;
sysread(STDIN,$rom,0xFFFF)&gt;0 or die;
print substr($rom,0,length($rom)-5)' &lt;foo.bin &gt;foo.rom
</code></pre>
<p>This ROM image can be tested in the XRoar emulator this way:</p>
<pre><code>xroar -machine cocous -cart-autorun -cart color8.rom
</code></pre>
<p>Note that XRoar requires the image file to have the .rom extension.</p>
<p>Note that in a program written as above, the IRQ interrupt is
not enabled, so Basic's TIMER counter (at $0112) does not get
incremented. To enable the IRQ in your catridge-based program,
put this at the beginning of the main() function:</p>
<pre><code>asm
{
// We come here from a JMP $C000 in Color Basic (normally at $A10A in v1.2).
// At this point, the 60 Hz interrupt has not been enabled yet, so enable it.
lda $ff03 // get control register of PIA0, port B
ora #1
sta $ff03 // enable 60 Hz interrupt
// Unmask interrupts to allow the timer IRQ to be processed.
andcc #$af
}
</code></pre>
<h3><a name="t41"></a>Detecting null pointer accesses at run time</h3>
<p>Accessing a value through a null pointer is a common bug.
To help detect such accesses, CMOC has the --check-null command-line
option, which adds run-time checks before every use of a pointer and
every array element access.</p>
<p>By default, the handler that is invoked when a null pointer access
is detected is a no-op. The program should start by calling the
<code>set_null_ptr_handler()</code> function to set up a handler that will
receive the address of the failed check as an argument. For example:</p>
<pre><code>#include &lt;cmoc.h&gt;
struct S { int n; };
void nullPointerHandler(char *addressOfFailedCheck)
{
printf("[FAIL: %p]\n", addressOfFailedCheck);
exit(1);
}
int main()
{
set_null_ptr_handler(nullPointerHandler);
struct S *p = 0;
p-&gt;n = 42;
return 0;
}
</code></pre>
<p>This program will fail and display an address. One can then look up
this address in the .lst listing file generated by CMOC to determine
in which function that null pointer was detected.</p>
<p>Using this option incurs a performance cost, so it is only recommended
during debugging. An alternative is to define an <code>assert()</code> macro that
expands to nothing when <code>NDEBUG</code> is defined.</p>
<h3><a name="t42"></a>Detecting stack overflows at run time</h3>
<p>Runaway recursion or excessively long local arrays can cause corruption
that is difficult to investigate. To help detect stack overflows,
CMOC has the --check-stack command-line option, which adds run-time checks
at the beginning of each function body.</p>
<p>When passing --check-stack to CMOC, the program should start with
a call to <code>set_stack_overflow_handler()</code> that installs a handler.
This handler receives two arguments: the address of the failed check
and the out-of-range stack pointer. The handler must not return.
For example:</p>
<pre><code>void stackOverflowHandler(char *addressOfFailedCheck, char *stackRegister)
{
printf("[FAIL: %p, %p]\n", addressOfFailedCheck, stackRegister);
exit(1);
}
void recurse() { recurse(); }
int main()
{
set_stack_overflow_handler(stackOverflowHandler);
recurse();
return 0;
}
</code></pre>
<p>This program will fail and display two addresses. One can look up
the first one in the .lst listing file generated by CMOC to determine
in which function that stack overflow was detected.</p>
<p>Using this option incurs a performance cost, so it is only recommended
during debugging.</p>
<p>CMOC allocates 1024 bytes for the stack. In a program that is compiled
with the default layout, the stack is preceded by the memory managed
by sbrk() (see elsewhere in this manual).</p>
<h3><a name="t43"></a>Single-execution programs</h3>
<p>If a program is intended to be executable only once, i.e., that
reloading it or rebooting the CoCo is required to run it again,
then the code that initializes the writable global variables is
not needed upon entry to function main().</p>
<p>This routine is assembled at the very end of the code section.
When the program specifies <code>#pragma exec_once</code>, then the "program
break" used by sbrk() (see the previous section) is placed at
the start of the routine. This makes the memory of that routine
available to be allocated by sbrk().</p>
<h3><a name="t44"></a>Calling convention</h3>
<p>CMOC follows the C convention of passing the parameters in the stack
in the reverse order.</p>
<p>The caller pops them off the stack after the call.</p>
<p>An argument of type <code>char</code>, which is signed, is promoted to <code>int</code>.</p>
<p>An argument of type <code>unsigned char</code> is promoted to <code>unsigned int</code>.</p>
<p>When the return value is requested to be an r-value, is expected in
the B register for a byte-size type or D for a word-size type. For
an l-value, the return value must be left in X.</p>
<p>The body of a function must preserve registers U and S. It is
allowed to modify A, B, X and CC. </p>
<p><strong>Under OS-9, CMOC uses Y to refer to the data section</strong> of the current
process. Any code that needs to use Y must preserve its value and
restore it when finished.</p>
<p>The called function does not have to return any particular condition
codes.</p>
<p>Register DP is not used or modified by CMOC-generated code.</p>
<p>A CMOC-generated function uses a stack frame if the function receives
one or more parameters or has local variables, and is not defined
with the <code>asm</code> keyword (see the <em>Assembly-only functions</em> section
elsewhere in this manual).
Register U is used as the stack frame
pointer. Such a function starts with these instructions:</p>
<pre><code> PSHS U
LEAU ,S
</code></pre>
<p>an ends with these:</p>
<pre><code> LEAS ,U
PULS U,PC
</code></pre>
<h3><a name="t45"></a>Compiling a program executable by the DOS command</h3>
<p>Disk Basic 1.1 has a DOS command that loads track 34 at $2600
and if the contents start with the bytes 'O' and 'S', the interpreter
jumps at $2602.</p>
<p>CMOC can accommodate this with its --dos option. It implies --coco,
it uses $2600 as the code origin, and it generates the "OS" marker
at that address.</p>
<p>The output is still a .bin file. CMOC comes with a command-line tool
called <code>install-coco-boot-loader</code> that takes this file and copies
it to track 34 of a DECB disk image. For example:</p>
<pre><code>cmoc --dos prog.c
install-coco-boot-loader foo.dsk prog.bin
</code></pre>
<p>This tool will fail if track 34 is already occupied. It has a <code>--force</code>
option that will install the boot leader despite that.</p>
<p>To uninstall the boot loader, use the <code>--uninstall</code> option:</p>
<pre><code>install-coco-boot-loader --uninstall foo.dsk
</code></pre>
<h3><a name="t46"></a>Unused functions</h3>
<p>A C function that is not called and whose address is not taken will
not have assembly language generated for it by CMOC.</p>
<p>This means that a library can be implemented as a header file
containing several functions, without having to worry about bloating
an executable that would only use some of those functions.</p>
<h2><a name="t47"></a>License</h2>
<p><strong>EXCEPT FOR THE FILES UNDER src/usim-0.91-cmoc in the CMOC source archive,
CMOC is distributed under the following license:</strong></p>
<p>This program is free software: you can redistribute it and/or modify
it under the terms of the <strong>GNU General Public License</strong> as published by
the Free Software Foundation, <strong>either version 3 of the License, or
(at your option) any later version.</strong></p>
<p>This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.</p>
<p>You should have received a copy of the GNU General Public License
along with this program. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.</p>
<p></p>
</body></html>