SDCC Part 2 of 4 : Compiling our first C program
In my previous article related to SDCC, I explained why using C language for the Amstrad CPC is a completely viable solution and also why I decided to stick with SDCC compiler.
This article now shows you the steps to build your own program using SDCC.
This article now shows you the steps to build your own program using SDCC.
Software requirements
First, you need to download latest version of SDCC from Sourceforge here. The compiler is available for all mainstream systems (Windows, MacOSX, Linux) but I recommend you to stick on Windows version. Mainly because you will eventually need other tools later, such as an emulator or a DSK file manager.
Next, you need a good text editor. If you don't have one, I recommend you to use Notepad++ (Sourceforge) which features everything needed for serious development (color syntax, multiple files editing, macros, and lots more).
Finally, you need to download hex2bin from Sourceforge here. It will be used later to convert SDCC output to binary data (that will represent our CPC file to be executed).
Next, you need a good text editor. If you don't have one, I recommend you to use Notepad++ (Sourceforge) which features everything needed for serious development (color syntax, multiple files editing, macros, and lots more).
Finally, you need to download hex2bin from Sourceforge here. It will be used later to convert SDCC output to binary data (that will represent our CPC file to be executed).
Disclaimer
Before going further with the presentation, I want to inform you that a better solution exists, and will be presented in Part 3 of this series of tutorial. That said, I have been able to create an entire demo using this development scheme (Pheelone), and it was not that bad. Finally, know that the biggest part of this presentation will remain valid for the next article dealing with SDCC.
Our very first C program
Oh no! Our first program won't be the classical Hello World! This article is all about the basics, the how-to of the compilation. Dealing with an Hello World! example would require me to explain you inline assembly language because it has to make use of target machine's display char output.
Instead of that, we will focus on this very simple C program, that does nothing more than looping 10 times and then exits with 0 value :
int main()
{
int a;
for ( a = 0; a < 10; a++ )
{
}
return 0;
}
Copy-paste this small source code in your favorite text editor and save it with main.c as filename.
Instead of that, we will focus on this very simple C program, that does nothing more than looping 10 times and then exits with 0 value :
int main()
{
int a;
for ( a = 0; a < 10; a++ )
{
}
return 0;
}
Copy-paste this small source code in your favorite text editor and save it with main.c as filename.
Compiling
To compile main.c, use the command line and execute the following :
sdcc -mz80 --no-std-crt0 --vc --code-loc 16384 main.c
This will tell SDCC to compile the file main.c at origin &4000 (=16384 in decimal) using VisualC output-style (useful for error handling) without including default CRT implementation, and of course targeting Z80 processor. At this point, remember that SDCC targets Z80 processor, and not Amstrad CPC.
Few files will be generated, the ones that matters are main.asm and main.ihx.
sdcc -mz80 --no-std-crt0 --vc --code-loc 16384 main.c
This will tell SDCC to compile the file main.c at origin &4000 (=16384 in decimal) using VisualC output-style (useful for error handling) without including default CRT implementation, and of course targeting Z80 processor. At this point, remember that SDCC targets Z80 processor, and not Amstrad CPC.
Few files will be generated, the ones that matters are main.asm and main.ihx.
Some words about generated code
What is interesting is the main.asm generated file. It represents the output of C to ASM conversion :
_main:
;main.c:6: for ( a = 0; a < 10; a++ )
ld bc,#0x000A
00103$:
dec bc
ld a,c
or a,b
jr NZ,00103$
;main.c:10: return 0;
ld hl,#0x0000
ret
As you see, the output is clean ; considering we declared our loop iterator as an int (which is 16 bits). It makes use of registers, where other compilers would use stack to store data and custom functions to substract a value with an other one.
Also, take note that produced assembly language is not conform to the Maxam convention we generally use on Amstrad CPC. This problem will be adressed in Part 3, that's why I did not wish to present you assembly language in this article. To release Pheelone demo, I had to learn this new syntax, which is really not natural even after months of development :) You never know when to use # sign. There are tons of other boring use-cases like this not presented with this example. Still, it's nice SDCC features a complete development system, taking care of compilation from C source to binary output.
_main:
;main.c:6: for ( a = 0; a < 10; a++ )
ld bc,#0x000A
00103$:
dec bc
ld a,c
or a,b
jr NZ,00103$
;main.c:10: return 0;
ld hl,#0x0000
ret
As you see, the output is clean ; considering we declared our loop iterator as an int (which is 16 bits). It makes use of registers, where other compilers would use stack to store data and custom functions to substract a value with an other one.
Also, take note that produced assembly language is not conform to the Maxam convention we generally use on Amstrad CPC. This problem will be adressed in Part 3, that's why I did not wish to present you assembly language in this article. To release Pheelone demo, I had to learn this new syntax, which is really not natural even after months of development :) You never know when to use # sign. There are tons of other boring use-cases like this not presented with this example. Still, it's nice SDCC features a complete development system, taking care of compilation from C source to binary output.
Getting our binary file for the Amstrad CPC
Remember our main.ihx file ? It represents the compiled version of main.asm file. SDCC internally use as-z80 as Z80 assembly language compiler. This assembler outputs binary file in Intel hex format, which is kind of text-format with opcodes in it :
:03400000010A00B2
:094003000B79B020FB210000C97B
:00000001FF
That's where you have to use hex2bin tool presented in Software requirements section in this article. Its aim is to convert this text file to a binary file.
Use the following command :
hex2bin -p 00 main.ihx
And that's it. A file main.bin will be generated, having this content when opened with an hexadecimal editor :
01 0A 00 0B 79 B0 20 FB 21 00 00 C9
:03400000010A00B2
:094003000B79B020FB210000C97B
:00000001FF
That's where you have to use hex2bin tool presented in Software requirements section in this article. Its aim is to convert this text file to a binary file.
Use the following command :
hex2bin -p 00 main.ihx
And that's it. A file main.bin will be generated, having this content when opened with an hexadecimal editor :
01 0A 00 0B 79 B0 20 FB 21 00 00 C9
Conclusion
Here we are. It was not that hard, was it ? So now you have your final binary file, ready to be injected inside a DSK file, and ready to be tested under an emulator (or a real Amstrad CPC). Next tutorial of this series will cover how to use Maxam syntax for your inlined asm code inside your own C programs to be compiled with SDCC.
If this article was not clear enough for you, feel free to contact me and I will eventually add any missing information to the article !
If this article was not clear enough for you, feel free to contact me and I will eventually add any missing information to the article !