<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://library.morph.zone/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AusPPC</id>
		<title>MorphOS Library - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://library.morph.zone/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AusPPC"/>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/Special:Contributions/AusPPC"/>
		<updated>2026-04-22T12:33:12Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1288</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1288"/>
				<updated>2011-02-16T08:40:06Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Fixed bad link to source archive.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS_PPC_HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
&lt;br /&gt;
.global	__abox__		#__abox__ is a special MorphOS symbol that will &lt;br /&gt;
__abox__:			#differentiate this program from other PPC &lt;br /&gt;
.word	1			#executables that can run on MorphOS...  &lt;br /&gt;
.type	__abox__,@object	#When linking, care should be taken &lt;br /&gt;
.size	__abox__,4		#to avoid stripping this symbol.  &lt;br /&gt;
&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for ''include:'' and, if your system already assigns ''include:'' to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my ''S:user-startup'' after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with ''objdump'' although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing ''objdump'' not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
''objdump'' can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with ''vasm'' as before but note that the resulting object file is no longer executable.  To make this object executable, ''vlink'' is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, ''-lamiga'' refers to the ''libamiga.a'' file that ''vlink'' knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above ''vlink'' command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''-s''' strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
'''-P&amp;lt;symbol&amp;gt;''' preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for ''vlink'' and other programs installed with ''vbcc''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1155</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1155"/>
				<updated>2011-01-22T09:33:20Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: The __abox__ symbol was incorrectly defined in the source example.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
&lt;br /&gt;
.global	__abox__		#__abox__ is a special MorphOS symbol that will &lt;br /&gt;
__abox__:			#differentiate this program from other PPC &lt;br /&gt;
.word	1			#executables that can run on MorphOS...  &lt;br /&gt;
.type	__abox__,@object	#When linking, care should be taken &lt;br /&gt;
.size	__abox__,4		#to avoid stripping this symbol.  &lt;br /&gt;
&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for ''include:'' and, if your system already assigns ''include:'' to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my ''S:user-startup'' after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with ''objdump'' although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing ''objdump'' not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
''objdump'' can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with ''vasm'' as before but note that the resulting object file is no longer executable.  To make this object executable, ''vlink'' is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, ''-lamiga'' refers to the ''libamiga.a'' file that ''vlink'' knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above ''vlink'' command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''-s''' strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
'''-P&amp;lt;symbol&amp;gt;''' preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for ''vlink'' and other programs installed with ''vbcc''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1079</id>
		<title>Text Class: Buttons, Textfields, Labels</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1079"/>
				<updated>2011-01-07T07:34:20Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Buttons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The ''Text'' class is the most commonly used one for creating gadgets. This is because it not only creates plain labels (also called &amp;quot;static text&amp;quot; in other GUI engines), but also framed read-only text gadgets and textual buttons. In fact MUI has no special class for buttons, a button is just a ''Text'' object with a proper frame and background and user input activated. This versatility can have the disadvantage of allowing for creation of style guide nonconforming interfaces.&lt;br /&gt;
&lt;br /&gt;
The ''Text'' class uses the [[MUI Text Rendering Engine]] for text output. It allows for multiline text, using styles (bold, italic), colors and inlined images. These features should be used sparingly to keep user interfaces consistent and comfortable to use. The rendering engine is controlled by inserting escape sequences in the text. Another engine feature is aligning the text inside the object rectangle (left, right, centered).&lt;br /&gt;
&lt;br /&gt;
==Common Attributes==&lt;br /&gt;
&lt;br /&gt;
*'''''MUIA_Background''''' and '''''MUIA_Frame''''' are attributes inherited from the ''Area'' class. They specify a background and frame used for an object.&lt;br /&gt;
*'''''MUIA_Text_Contents''''' specifies the text. It may contain formatting engine escape sequences. The text is buffered internally, so the value of this attribute may point to a local variable or a dynamically allocated buffer.&lt;br /&gt;
*'''''MUIA_Text_PreParse''''' may be considered a fixed prefix, which is always added at the start of text before rendering. It is usually used for applying constant styles and formatting, for example setting it to &amp;quot;\33c&amp;quot; will always center the text. This attribute simplifies text handling when the text displayed is not constant (for example is loaded from a locale catalog). &lt;br /&gt;
*'''''MUIA_Font''''' is another attribute inherited from the ''Area'' class and specifies a font to be used for text rendering. In most cases it is one of the fonts predefined by the user in MUI settings.&lt;br /&gt;
&lt;br /&gt;
For more attributes and detailed descriptions refer to the ''Text'' class autodoc in the SDK.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
&lt;br /&gt;
Labels are the simplest form of ''Text'' instances. They have no frame and inherit their background from the parent object (neither ''MUIA_Frame'' nor ''MUIA_Background'' is specified). They use the standard MUI font in most cases, so ''MUIA_Font'' does not need to be specified either. An important (and often forgotten) detail is a proper text baseline align when a label is used with some framed gadget also containing text (a ''String'' gadget for example). The default MUI behaviour for vertical text positioning is to center it. If the framed gadget uses uneven vertical padding, baselines of the label and the gadget may be unaligned. A special attribute ''MUIA_FramePhantomHoriz'' solves this problem. It is specified for a label with a ''TRUE'' value. The label also has ''MUIA_Frame'' specified with the same frame type as the gadget. Then the label gets an invisible frame of this type (frame horizontal parts to be exact, hence the attribute name) and the text is laid out accordingly. As a result the label and the gadget text are always aligned vertically, assuming they use the same font. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Label_align.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The magnified screenshot above illustrates the label align problem. The string gadget uses uneven padding (top padding is 2 pixels, bottom padding is 0 pixels), which causes the text baseline to misalign by 1 pixel shown on the left. The label on the right has been defined with two additional tags:&lt;br /&gt;
&lt;br /&gt;
 MUIA_FramePhantomHoriz,  TRUE,&lt;br /&gt;
 MUIA_Frame,              MUIV_Frame_String,&lt;br /&gt;
&lt;br /&gt;
A label can have one character underlined with the ''MUIA_Text_HiChar'' attribute. It is used to create a visual hint for a hotkey of a labeled gadget. See [[#Buttons|Buttons]] section below for details.&lt;br /&gt;
&lt;br /&gt;
==Textfields==&lt;br /&gt;
&lt;br /&gt;
A textfield is a read-only framed area showing some (usually changing at runtime) text. The difference between a label and a textfield is that the latter has a frame and a background specified:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Text,&lt;br /&gt;
 MUIA_Background,        MUII_TextBack,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Buttons==&lt;br /&gt;
A text button is an instance of the ''Text'' class too. It has more attributes than a plain label however, because it handles user input. MUI has a predefined background and frame for buttons:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Button,&lt;br /&gt;
 MUIA_Background,        MUII_ButtonBack,&lt;br /&gt;
&lt;br /&gt;
These attributes also specify a frame and background for the &amp;quot;pressed&amp;quot; state. MUI also has separate font settings for buttons. Forgetting the ''MUIA_Font'' attribute for buttons is one of most common errors in MUI design.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Font,              MUIV_Font_Button,&lt;br /&gt;
&lt;br /&gt;
Many users (and programmers) just have the default font defined for buttons, so the bug is not visible. It is recommended to always test a GUI with some unusual font settings for buttons, so the problem is easily visible. Button text is usually centered, which may be done either by inserting the &amp;quot;\33c&amp;quot; sequence at the start of the button label, or using ''MUIA_Text_PreParse''.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_PreParse,     &amp;quot;\33c&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
After definition of the button appearance it is time to handle user input. The button behaviour is defined by the ''MUIA_InputMode'' attribute with three values:&lt;br /&gt;
*'''''MUIV_InputMode_None''''' &amp;amp;ndash; The default value, button does not react on anything.&lt;br /&gt;
*'''''MUIV_InputMode_RelVerify''''' &amp;amp;ndash; A simple pushbutton activated by a left mouse button click.&lt;br /&gt;
*'''''MUIV_InputMode_Toggle''''' &amp;amp;ndash; A two-state button, one click switches it on, another one switches it off.&lt;br /&gt;
&lt;br /&gt;
Another common bug with MUI buttons is to omit keyboard handling. The mouse is not everything. The first, obligatory step is to enter the button into the window's TAB key cycle chain:&lt;br /&gt;
&lt;br /&gt;
 MUIA_CycleChain,        TRUE,&lt;br /&gt;
&lt;br /&gt;
Any gadget entered into the chain may be selected by pressing the TAB key (for default MUI keyboard settings). The selected object has a special frame drawn around it. Then it may be activated by some key set in MUI preferences. For buttons the default &amp;quot;pressing&amp;quot; key is the return key. A rule of thumb for cycle chaining:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;center&amp;gt;'''Every''' gadget accepting user input '''must''' be added to the TAB cycle chain.&amp;lt;/center&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another keyboard handling feature provided by MUI is hotkeys. A hotkey just activates a button associated to it. Hotkeys have the following features:&lt;br /&gt;
*MUI provides a visual hint of a button hotkey by underlining the hotkey letter in the button label. It implies that the hotkey letter must exist in the label.&lt;br /&gt;
*There is visual feedback for using a hotkey, the button is pressed as if it has been clicked with the mouse.&lt;br /&gt;
Not every button in a GUI has to have a hotkey. The best practice is to assign hotkeys only for the most used buttons, especially if there are many buttons in a window. A hotkey is defined with two attributes:&lt;br /&gt;
*'''''MUIA_Text_HiChar''''' &amp;amp;ndash; this attribute specifies a letter to be underlined in the label. It is case insensitive.&lt;br /&gt;
*'''''MUIA_ControlChar''''' &amp;amp;ndash; this attribute specifies a hotkey. Of course it should be the same as the above one. It should be a lowercase letter, as uppercase forces a user to press SHIFT, making the hotkey less comfortable to use. There is also no visual hint for SHIFT requirement. Digits may be also used as hotkeys if the label contains them. Using punctuation and other characters should be avoided. An example of use:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_Contents,     &amp;quot;Destroy All&amp;quot;,&lt;br /&gt;
 MUIA_Text_HiChar,       'a',&lt;br /&gt;
 MUIA_Text_ControlChar,  'a'&lt;br /&gt;
&lt;br /&gt;
Note that these attributes take a single char, not a string.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1078</id>
		<title>Text Class: Buttons, Textfields, Labels</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1078"/>
				<updated>2011-01-07T07:26:08Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Labels */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The ''Text'' class is the most commonly used one for creating gadgets. This is because it not only creates plain labels (also called &amp;quot;static text&amp;quot; in other GUI engines), but also framed read-only text gadgets and textual buttons. In fact MUI has no special class for buttons, a button is just a ''Text'' object with a proper frame and background and user input activated. This versatility can have the disadvantage of allowing for creation of style guide nonconforming interfaces.&lt;br /&gt;
&lt;br /&gt;
The ''Text'' class uses the [[MUI Text Rendering Engine]] for text output. It allows for multiline text, using styles (bold, italic), colors and inlined images. These features should be used sparingly to keep user interfaces consistent and comfortable to use. The rendering engine is controlled by inserting escape sequences in the text. Another engine feature is aligning the text inside the object rectangle (left, right, centered).&lt;br /&gt;
&lt;br /&gt;
==Common Attributes==&lt;br /&gt;
&lt;br /&gt;
*'''''MUIA_Background''''' and '''''MUIA_Frame''''' are attributes inherited from the ''Area'' class. They specify a background and frame used for an object.&lt;br /&gt;
*'''''MUIA_Text_Contents''''' specifies the text. It may contain formatting engine escape sequences. The text is buffered internally, so the value of this attribute may point to a local variable or a dynamically allocated buffer.&lt;br /&gt;
*'''''MUIA_Text_PreParse''''' may be considered a fixed prefix, which is always added at the start of text before rendering. It is usually used for applying constant styles and formatting, for example setting it to &amp;quot;\33c&amp;quot; will always center the text. This attribute simplifies text handling when the text displayed is not constant (for example is loaded from a locale catalog). &lt;br /&gt;
*'''''MUIA_Font''''' is another attribute inherited from the ''Area'' class and specifies a font to be used for text rendering. In most cases it is one of the fonts predefined by the user in MUI settings.&lt;br /&gt;
&lt;br /&gt;
For more attributes and detailed descriptions refer to the ''Text'' class autodoc in the SDK.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
&lt;br /&gt;
Labels are the simplest form of ''Text'' instances. They have no frame and inherit their background from the parent object (neither ''MUIA_Frame'' nor ''MUIA_Background'' is specified). They use the standard MUI font in most cases, so ''MUIA_Font'' does not need to be specified either. An important (and often forgotten) detail is a proper text baseline align when a label is used with some framed gadget also containing text (a ''String'' gadget for example). The default MUI behaviour for vertical text positioning is to center it. If the framed gadget uses uneven vertical padding, baselines of the label and the gadget may be unaligned. A special attribute ''MUIA_FramePhantomHoriz'' solves this problem. It is specified for a label with a ''TRUE'' value. The label also has ''MUIA_Frame'' specified with the same frame type as the gadget. Then the label gets an invisible frame of this type (frame horizontal parts to be exact, hence the attribute name) and the text is laid out accordingly. As a result the label and the gadget text are always aligned vertically, assuming they use the same font. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Label_align.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The magnified screenshot above illustrates the label align problem. The string gadget uses uneven padding (top padding is 2 pixels, bottom padding is 0 pixels), which causes the text baseline to misalign by 1 pixel shown on the left. The label on the right has been defined with two additional tags:&lt;br /&gt;
&lt;br /&gt;
 MUIA_FramePhantomHoriz,  TRUE,&lt;br /&gt;
 MUIA_Frame,              MUIV_Frame_String,&lt;br /&gt;
&lt;br /&gt;
A label can have one character underlined with the ''MUIA_Text_HiChar'' attribute. It is used to create a visual hint for a hotkey of a labeled gadget. See [[#Buttons|Buttons]] section below for details.&lt;br /&gt;
&lt;br /&gt;
==Textfields==&lt;br /&gt;
&lt;br /&gt;
A textfield is a read-only framed area showing some (usually changing at runtime) text. The difference between a label and a textfield is that the latter has a frame and a background specified:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Text,&lt;br /&gt;
 MUIA_Background,        MUII_TextBack,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Buttons==&lt;br /&gt;
A text button is an instance of the ''Text'' class too. It has more attributes than a plain label however, because it handles user input. MUI has a predefined background and frame for buttons:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Button,&lt;br /&gt;
 MUIA_Background,        MUII_ButtonBack,&lt;br /&gt;
&lt;br /&gt;
These attributes specify also frame and background for &amp;quot;pressed&amp;quot; state. MUI has also a separate font settings for buttons. Forgetting ''MUIA_Font'' attribute for buttons is one of most common errors in MUI design.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Font,              MUIV_Font_Button,&lt;br /&gt;
&lt;br /&gt;
Many users (and programmers) have just the default font defined for buttons, so the bug is not visible. It is recommended to always check a GUI with some unusual font settings for buttons, so the problem is easily visible. Button text is usually centered, which may be done either by inserting &amp;quot;\33c&amp;quot; sequence at the start of button label, or using ''MUIA_Text_PreParse''.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_PreParse,     &amp;quot;\33c&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
After definition of the button appearance it is time to handle user input. The button behaviour is defined by ''MUIA_InputMode'' attribute with three values:&lt;br /&gt;
*'''''MUIV_InputMode_None''''' &amp;amp;ndash; The default value, button does not react on anything.&lt;br /&gt;
*'''''MUIV_InputMode_RelVerify''''' &amp;amp;ndash; A simple pushbutton activated by a left mouse button click.&lt;br /&gt;
*'''''MUIV_InputMode_Toggle''''' &amp;amp;ndash; A two-state button, one click switches it on, another one switches off.&lt;br /&gt;
&lt;br /&gt;
Another common bug with MUI buttons is to ommit keyboard handling. Mouse is not everything. The first, obligatory step is to enter the button into the window's TAB key cycle chain:&lt;br /&gt;
&lt;br /&gt;
 MUIA_CycleChain,        TRUE,&lt;br /&gt;
&lt;br /&gt;
Any gadget entered into the chain may be selected by pressing the TAB key (for default MUI keyboard settings). The selected object has a special frame drawn around it. Then it may be activated by some key set in MUI preferences. For buttons the default &amp;quot;pressing&amp;quot; key is the return key. A rule of thumb for cycle chaining:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;center&amp;gt;'''Every''' gadget accepting user input '''must''' be added to the TAB cycle chain.&amp;lt;/center&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another keyboard handling feature provided by MUI are hotkeys. A hotkey just activates a button associated to it. Hotkeys have following features:&lt;br /&gt;
*MUI provides a visual hint of a button hotkey by underlining the hotkey letter in the button label. It implies that the hotkey letter must exist in the label.&lt;br /&gt;
*There is a visual feedback of using a hotkey, the button is pressed as if it has been clicked with the mouse.&lt;br /&gt;
Not every button in a GUI has to have a hotkey. The best practice is to assign hotkeys only for most used buttons, especially if there are many buttons in a window. A hotkey is defined with two attributes:&lt;br /&gt;
*'''''MUIA_Text_HiChar''''' &amp;amp;ndash; this attribute specifies a letter to be underlined in the label. It is case insensitive.&lt;br /&gt;
*'''''MUIA_ControlChar''''' &amp;amp;ndash; this attribute specifies a hotkey. Of course it should be the same as the above one. It should be a lowercase letter, as uppercase forces a user to press SHIFT, making the hotkey less comfortable. There is also no visual hint for SHIFT requirement. Digits may be also used as hotkeys if the label contains them. Using punctuation and other characters should be avoided. An example of use:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_Contents,     &amp;quot;Destroy All&amp;quot;,&lt;br /&gt;
 MUIA_Text_HiChar,       'a',&lt;br /&gt;
 MUIA_Text_ControlChar,  'a'&lt;br /&gt;
&lt;br /&gt;
Note that these attributes take a single char, not a string.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1077</id>
		<title>Text Class: Buttons, Textfields, Labels</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1077"/>
				<updated>2011-01-07T07:19:50Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Common Attributes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The ''Text'' class is the most commonly used one for creating gadgets. This is because it not only creates plain labels (also called &amp;quot;static text&amp;quot; in other GUI engines), but also framed read-only text gadgets and textual buttons. In fact MUI has no special class for buttons, a button is just a ''Text'' object with a proper frame and background and user input activated. This versatility can have the disadvantage of allowing for creation of style guide nonconforming interfaces.&lt;br /&gt;
&lt;br /&gt;
The ''Text'' class uses the [[MUI Text Rendering Engine]] for text output. It allows for multiline text, using styles (bold, italic), colors and inlined images. These features should be used sparingly to keep user interfaces consistent and comfortable to use. The rendering engine is controlled by inserting escape sequences in the text. Another engine feature is aligning the text inside the object rectangle (left, right, centered).&lt;br /&gt;
&lt;br /&gt;
==Common Attributes==&lt;br /&gt;
&lt;br /&gt;
*'''''MUIA_Background''''' and '''''MUIA_Frame''''' are attributes inherited from the ''Area'' class. They specify a background and frame used for an object.&lt;br /&gt;
*'''''MUIA_Text_Contents''''' specifies the text. It may contain formatting engine escape sequences. The text is buffered internally, so the value of this attribute may point to a local variable or a dynamically allocated buffer.&lt;br /&gt;
*'''''MUIA_Text_PreParse''''' may be considered a fixed prefix, which is always added at the start of text before rendering. It is usually used for applying constant styles and formatting, for example setting it to &amp;quot;\33c&amp;quot; will always center the text. This attribute simplifies text handling when the text displayed is not constant (for example is loaded from a locale catalog). &lt;br /&gt;
*'''''MUIA_Font''''' is another attribute inherited from the ''Area'' class and specifies a font to be used for text rendering. In most cases it is one of the fonts predefined by the user in MUI settings.&lt;br /&gt;
&lt;br /&gt;
For more attributes and detailed descriptions refer to the ''Text'' class autodoc in the SDK.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
&lt;br /&gt;
Labels are the simplest form of ''Text'' instances. They have no frame and inherit their background from the parent object (neither ''MUIA_Frame'' nor ''MUIA_Background'' is specified). They use the standard MUI font in most cases, so ''MUIA_Font'' needs not to be specified too. An important (and often forgotten) detail is a proper text baseline align when a label is used with some framed gadget containing text as well (a ''String'' gadget for example). The default MUI behaviour for vertical text positioning is to center it. If the framed gadget uses uneven vertical padding, baselines of the label and the gadget may be unaligned. A special attribute ''MUIA_FramePhantomHoriz'' solves this problem. It is specified for a label with ''TRUE'' value. The label has also ''MUIA_Frame'' specified with the same frame type as the gadget. Then the label gets an invisible frame of this type (frame horizontal parts to be exact, hence the attribute name) and the text is layouted accordingly. As a result the label and the gadget text are always aligned vertically, assuming they use the same font. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Label_align.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The magnified screenshot above illustrates the label align problem. The string gadget uses uneven padding (top padding is 2 pixels, bottom padding is 0 pixels), which causes text baseline misalign by 1 pixel shown on the left. The label on the right has been defined with two additional tags:&lt;br /&gt;
&lt;br /&gt;
 MUIA_FramePhantomHoriz,  TRUE,&lt;br /&gt;
 MUIA_Frame,              MUIV_Frame_String,&lt;br /&gt;
&lt;br /&gt;
A label can have one character underlined with ''MUIA_Text_HiChar'' attribute. It is used to create a visual hint for a hotkey of labelled gadget. See [[#Buttons|Buttons]] section below for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Textfields==&lt;br /&gt;
&lt;br /&gt;
A textfield is a read-only framed area showing some (usually changing at runtime) text. The difference between a label and a textfield is that the latter has a frame and a background specified:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Text,&lt;br /&gt;
 MUIA_Background,        MUII_TextBack,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Buttons==&lt;br /&gt;
A text button is an instance of the ''Text'' class too. It has more attributes than a plain label however, because it handles user input. MUI has a predefined background and frame for buttons:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Button,&lt;br /&gt;
 MUIA_Background,        MUII_ButtonBack,&lt;br /&gt;
&lt;br /&gt;
These attributes specify also frame and background for &amp;quot;pressed&amp;quot; state. MUI has also a separate font settings for buttons. Forgetting ''MUIA_Font'' attribute for buttons is one of most common errors in MUI design.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Font,              MUIV_Font_Button,&lt;br /&gt;
&lt;br /&gt;
Many users (and programmers) have just the default font defined for buttons, so the bug is not visible. It is recommended to always check a GUI with some unusual font settings for buttons, so the problem is easily visible. Button text is usually centered, which may be done either by inserting &amp;quot;\33c&amp;quot; sequence at the start of button label, or using ''MUIA_Text_PreParse''.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_PreParse,     &amp;quot;\33c&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
After definition of the button appearance it is time to handle user input. The button behaviour is defined by ''MUIA_InputMode'' attribute with three values:&lt;br /&gt;
*'''''MUIV_InputMode_None''''' &amp;amp;ndash; The default value, button does not react on anything.&lt;br /&gt;
*'''''MUIV_InputMode_RelVerify''''' &amp;amp;ndash; A simple pushbutton activated by a left mouse button click.&lt;br /&gt;
*'''''MUIV_InputMode_Toggle''''' &amp;amp;ndash; A two-state button, one click switches it on, another one switches off.&lt;br /&gt;
&lt;br /&gt;
Another common bug with MUI buttons is to ommit keyboard handling. Mouse is not everything. The first, obligatory step is to enter the button into the window's TAB key cycle chain:&lt;br /&gt;
&lt;br /&gt;
 MUIA_CycleChain,        TRUE,&lt;br /&gt;
&lt;br /&gt;
Any gadget entered into the chain may be selected by pressing the TAB key (for default MUI keyboard settings). The selected object has a special frame drawn around it. Then it may be activated by some key set in MUI preferences. For buttons the default &amp;quot;pressing&amp;quot; key is the return key. A rule of thumb for cycle chaining:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;center&amp;gt;'''Every''' gadget accepting user input '''must''' be added to the TAB cycle chain.&amp;lt;/center&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another keyboard handling feature provided by MUI are hotkeys. A hotkey just activates a button associated to it. Hotkeys have following features:&lt;br /&gt;
*MUI provides a visual hint of a button hotkey by underlining the hotkey letter in the button label. It implies that the hotkey letter must exist in the label.&lt;br /&gt;
*There is a visual feedback of using a hotkey, the button is pressed as if it has been clicked with the mouse.&lt;br /&gt;
Not every button in a GUI has to have a hotkey. The best practice is to assign hotkeys only for most used buttons, especially if there are many buttons in a window. A hotkey is defined with two attributes:&lt;br /&gt;
*'''''MUIA_Text_HiChar''''' &amp;amp;ndash; this attribute specifies a letter to be underlined in the label. It is case insensitive.&lt;br /&gt;
*'''''MUIA_ControlChar''''' &amp;amp;ndash; this attribute specifies a hotkey. Of course it should be the same as the above one. It should be a lowercase letter, as uppercase forces a user to press SHIFT, making the hotkey less comfortable. There is also no visual hint for SHIFT requirement. Digits may be also used as hotkeys if the label contains them. Using punctuation and other characters should be avoided. An example of use:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_Contents,     &amp;quot;Destroy All&amp;quot;,&lt;br /&gt;
 MUIA_Text_HiChar,       'a',&lt;br /&gt;
 MUIA_Text_ControlChar,  'a'&lt;br /&gt;
&lt;br /&gt;
Note that these attributes take a single char, not a string.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1076</id>
		<title>Text Class: Buttons, Textfields, Labels</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Text_Class:_Buttons,_Textfields,_Labels&amp;diff=1076"/>
				<updated>2011-01-07T07:17:18Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The ''Text'' class is the most commonly used one for creating gadgets. This is because it not only creates plain labels (also called &amp;quot;static text&amp;quot; in other GUI engines), but also framed read-only text gadgets and textual buttons. In fact MUI has no special class for buttons, a button is just a ''Text'' object with a proper frame and background and user input activated. This versatility can have the disadvantage of allowing for creation of style guide nonconforming interfaces.&lt;br /&gt;
&lt;br /&gt;
The ''Text'' class uses the [[MUI Text Rendering Engine]] for text output. It allows for multiline text, using styles (bold, italic), colors and inlined images. These features should be used sparingly to keep user interfaces consistent and comfortable to use. The rendering engine is controlled by inserting escape sequences in the text. Another engine feature is aligning the text inside the object rectangle (left, right, centered).&lt;br /&gt;
&lt;br /&gt;
==Common Attributes==&lt;br /&gt;
&lt;br /&gt;
*'''''MUIA_Background''''' and '''''MUIA_Frame''''' are attributes inherited from the ''Area'' class. They specify a background and frame used for an object.&lt;br /&gt;
*'''''MUIA_Text_Contents''''' specifies the text. It may contain formatting engine escape sequences. The text is buffered internally, so the value of this attribute may point to a local variable or a dynamically allocated buffer.&lt;br /&gt;
*'''''MUIA_Text_PreParse''''' may be considered a fixed prefix, which is always added at the start of text before rendering. It is usually used for applying a constant styles and formatting, for example setting it to &amp;quot;\33c&amp;quot; will always center the text. This attribute simplifies text handling when the text displayed is not constant (for example is loaded from a locale catalog). &lt;br /&gt;
*'''''MUIA_Font''''' is another attribute inherited from the ''Area'' class and specifies a font to be used for text rendeding. In most cases it is one of fonts predefined by user in MUI settings.&lt;br /&gt;
&lt;br /&gt;
For more attributes and detailed descriptions refer to the ''Text'' class autodoc in the SDK.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
&lt;br /&gt;
Labels are the simplest form of ''Text'' instances. They have no frame and inherit their background from the parent object (neither ''MUIA_Frame'' nor ''MUIA_Background'' is specified). They use the standard MUI font in most cases, so ''MUIA_Font'' needs not to be specified too. An important (and often forgotten) detail is a proper text baseline align when a label is used with some framed gadget containing text as well (a ''String'' gadget for example). The default MUI behaviour for vertical text positioning is to center it. If the framed gadget uses uneven vertical padding, baselines of the label and the gadget may be unaligned. A special attribute ''MUIA_FramePhantomHoriz'' solves this problem. It is specified for a label with ''TRUE'' value. The label has also ''MUIA_Frame'' specified with the same frame type as the gadget. Then the label gets an invisible frame of this type (frame horizontal parts to be exact, hence the attribute name) and the text is layouted accordingly. As a result the label and the gadget text are always aligned vertically, assuming they use the same font. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Label_align.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The magnified screenshot above illustrates the label align problem. The string gadget uses uneven padding (top padding is 2 pixels, bottom padding is 0 pixels), which causes text baseline misalign by 1 pixel shown on the left. The label on the right has been defined with two additional tags:&lt;br /&gt;
&lt;br /&gt;
 MUIA_FramePhantomHoriz,  TRUE,&lt;br /&gt;
 MUIA_Frame,              MUIV_Frame_String,&lt;br /&gt;
&lt;br /&gt;
A label can have one character underlined with ''MUIA_Text_HiChar'' attribute. It is used to create a visual hint for a hotkey of labelled gadget. See [[#Buttons|Buttons]] section below for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Textfields==&lt;br /&gt;
&lt;br /&gt;
A textfield is a read-only framed area showing some (usually changing at runtime) text. The difference between a label and a textfield is that the latter has a frame and a background specified:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Text,&lt;br /&gt;
 MUIA_Background,        MUII_TextBack,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Buttons==&lt;br /&gt;
A text button is an instance of the ''Text'' class too. It has more attributes than a plain label however, because it handles user input. MUI has a predefined background and frame for buttons:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Frame,             MUIV_Frame_Button,&lt;br /&gt;
 MUIA_Background,        MUII_ButtonBack,&lt;br /&gt;
&lt;br /&gt;
These attributes specify also frame and background for &amp;quot;pressed&amp;quot; state. MUI has also a separate font settings for buttons. Forgetting ''MUIA_Font'' attribute for buttons is one of most common errors in MUI design.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Font,              MUIV_Font_Button,&lt;br /&gt;
&lt;br /&gt;
Many users (and programmers) have just the default font defined for buttons, so the bug is not visible. It is recommended to always check a GUI with some unusual font settings for buttons, so the problem is easily visible. Button text is usually centered, which may be done either by inserting &amp;quot;\33c&amp;quot; sequence at the start of button label, or using ''MUIA_Text_PreParse''.&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_PreParse,     &amp;quot;\33c&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
After definition of the button appearance it is time to handle user input. The button behaviour is defined by ''MUIA_InputMode'' attribute with three values:&lt;br /&gt;
*'''''MUIV_InputMode_None''''' &amp;amp;ndash; The default value, button does not react on anything.&lt;br /&gt;
*'''''MUIV_InputMode_RelVerify''''' &amp;amp;ndash; A simple pushbutton activated by a left mouse button click.&lt;br /&gt;
*'''''MUIV_InputMode_Toggle''''' &amp;amp;ndash; A two-state button, one click switches it on, another one switches off.&lt;br /&gt;
&lt;br /&gt;
Another common bug with MUI buttons is to ommit keyboard handling. Mouse is not everything. The first, obligatory step is to enter the button into the window's TAB key cycle chain:&lt;br /&gt;
&lt;br /&gt;
 MUIA_CycleChain,        TRUE,&lt;br /&gt;
&lt;br /&gt;
Any gadget entered into the chain may be selected by pressing the TAB key (for default MUI keyboard settings). The selected object has a special frame drawn around it. Then it may be activated by some key set in MUI preferences. For buttons the default &amp;quot;pressing&amp;quot; key is the return key. A rule of thumb for cycle chaining:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;center&amp;gt;'''Every''' gadget accepting user input '''must''' be added to the TAB cycle chain.&amp;lt;/center&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another keyboard handling feature provided by MUI are hotkeys. A hotkey just activates a button associated to it. Hotkeys have following features:&lt;br /&gt;
*MUI provides a visual hint of a button hotkey by underlining the hotkey letter in the button label. It implies that the hotkey letter must exist in the label.&lt;br /&gt;
*There is a visual feedback of using a hotkey, the button is pressed as if it has been clicked with the mouse.&lt;br /&gt;
Not every button in a GUI has to have a hotkey. The best practice is to assign hotkeys only for most used buttons, especially if there are many buttons in a window. A hotkey is defined with two attributes:&lt;br /&gt;
*'''''MUIA_Text_HiChar''''' &amp;amp;ndash; this attribute specifies a letter to be underlined in the label. It is case insensitive.&lt;br /&gt;
*'''''MUIA_ControlChar''''' &amp;amp;ndash; this attribute specifies a hotkey. Of course it should be the same as the above one. It should be a lowercase letter, as uppercase forces a user to press SHIFT, making the hotkey less comfortable. There is also no visual hint for SHIFT requirement. Digits may be also used as hotkeys if the label contains them. Using punctuation and other characters should be avoided. An example of use:&lt;br /&gt;
&lt;br /&gt;
 MUIA_Text_Contents,     &amp;quot;Destroy All&amp;quot;,&lt;br /&gt;
 MUIA_Text_HiChar,       'a',&lt;br /&gt;
 MUIA_Text_ControlChar,  'a'&lt;br /&gt;
&lt;br /&gt;
Note that these attributes take a single char, not a string.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Locating_Objects_in_the_Object_Tree&amp;diff=1075</id>
		<title>Locating Objects in the Object Tree</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Locating_Objects_in_the_Object_Tree&amp;diff=1075"/>
				<updated>2011-01-07T06:53:09Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;After the complete object tree is created, there is no direct access to any object except the main ''Application'' object. A way to access other objects is needed. There are a few ways to do this:&lt;br /&gt;
* Storing pointers to objects in global variables. This is the simplest way and may work well in simple projects. The disadvantage is it breaks object oriented design principles (like data encapsulation) and creates a mess when the number of global variables reaches 50, 100 or more. &lt;br /&gt;
* Store pointers in fields of some subclass instance data (for example the ''Application'' instance). A good idea, but a bit tedious to implement. An object's instance data area does not exist until the object is fully created and the ''Application'' object is created as the last one. Then pointers to subobjects have to be stored in some temporary variables. This technique also requires that a parent object of the cached one is an instance of a custom (subclassed) class and the parent creates its subobjects inside the constructor, which is not always true.&lt;br /&gt;
* Use the ''MUIA_UserData'' attribute and the ''MUIM_FindUData()'' method to find objects dynamically. This is the best solution when objects are accessed rarely (for example once, just to set notifications). For frequently accessed objects (let's say several times a second) it may be combined with caching objects' pointers in an instance data of some subclassed object.&lt;br /&gt;
The last approach works as follows: every object to be searched has the ''MUIA_UserData'' attribute set to some predefined unique value. Then at any time the object may be found by this value using the ''MUIM_FindUData()'' method on a direct or indirect parent object, for example on the master ''Application'' object.&lt;br /&gt;
&lt;br /&gt;
 #define OBJ_SOME_BUTTON 36&lt;br /&gt;
 &lt;br /&gt;
 /* Somewhere in the initial tags for the button */&lt;br /&gt;
 MUIA_UserData, OBJ_SOME_BUTTON,&lt;br /&gt;
 /* ... */&lt;br /&gt;
 &lt;br /&gt;
 /* Let's get the pointer to the button now */&lt;br /&gt;
 &lt;br /&gt;
 Object *some_button;&lt;br /&gt;
 &lt;br /&gt;
 some_button = (Object*)DoMethod(App, MUIM_FindUData, OBJ_SOME_BUTTON);&lt;br /&gt;
&lt;br /&gt;
This operation is so common that it is usually encapsulated in a macro:&lt;br /&gt;
&lt;br /&gt;
 #define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)&lt;br /&gt;
 &lt;br /&gt;
 some_button = findobj(OBJ_SOME_BUTTON, App);&lt;br /&gt;
&lt;br /&gt;
The macro may of course be used directly in other functions, like in this example changing the button label:&lt;br /&gt;
&lt;br /&gt;
 set(findobj(OBJ_SOME_BUTTON, App), MUIA_Text_Contents, &amp;quot;Press Me&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Note that the ''findobj()'' macro is not defined in the system MUI headers, so it should be defined in the application code.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1074</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1074"/>
				<updated>2011-01-07T06:47:05Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Implementing Functionality */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in the benchmarks. The file ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides timing for the five functions performing all the benchmarks. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
The planned MUI interface should allow the user to run every benchmark separately or run all of them. There is also a ''-large'' option, which increases memory sizes for calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of the original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved accuracy of time measurements however, this is out of scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-ified version is the instance data area of the subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should then be overridden.&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets also belong to the ''Text'' class, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of the ''Text'' class of course, is a toggle button. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but instead the ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains the &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to the ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes a nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with a label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed to it. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions for the application. There are five actions for running individual benchmarks and the sixth one for running all the tests and calculating the global result. Actions will be directly mapped to ''Application'' subclass methods. There is also one attribute connected with the &amp;quot;Large Data&amp;quot; button, it determines the sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at initialisation time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. GET-ability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template example and as such it has been generated with the [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must of course be created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves the programmer from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
The five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on the ''d-&amp;gt;LargeData'' switch variable. This variable is set with the ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via a notification. Then the status bar progress is cleared and some text is set to inform the user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may not be responding to user input for anything longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer when the application window is active. Of course offloading processor intensive tasks to a subprocess is a better solution in general cases, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usability problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with the ''RAWFMTFUNC_STRING'' constant, it works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting the status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to the single benchmark method anyway. The difference is it runs all 5 tests accumulating their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1073</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1073"/>
				<updated>2011-01-07T06:38:13Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Methods and Attributes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in the benchmarks. The file ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides timing for the five functions performing all the benchmarks. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
The planned MUI interface should allow the user to run every benchmark separately or run all of them. There is also a ''-large'' option, which increases memory sizes for calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of the original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved accuracy of time measurements however, this is out of scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-ified version is the instance data area of the subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should then be overridden.&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets also belong to the ''Text'' class, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of the ''Text'' class of course, is a toggle button. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but instead the ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains the &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to the ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes a nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with a label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed to it. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions for the application. There are five actions for running individual benchmarks and the sixth one for running all the tests and calculating the global result. Actions will be directly mapped to ''Application'' subclass methods. There is also one attribute connected with the &amp;quot;Large Data&amp;quot; button, it determines the sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at initialisation time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. GET-ability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template example and as such it has been generated with the [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must of course be created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves the programmer from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
Five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on ''d-&amp;gt;LargeData'' switch variable. This variable is set with ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via notification. Then the status bar progress is cleared and a text is set to inform a user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may be not responding for user input for a time longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer, when the application window is active. Of course offloading processor intenstve task to a subprocess is a better solution in general case, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usablility problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with ''RAWFMTFUNC_STRING'' constant works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to a single benchmark one anyway. The difference is it runs all 5 tests accumulatig their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1072</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1072"/>
				<updated>2011-01-07T06:35:48Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Methods and Attributes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in the benchmarks. The file ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides timing for the five functions performing all the benchmarks. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
The planned MUI interface should allow the user to run every benchmark separately or run all of them. There is also a ''-large'' option, which increases memory sizes for calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of the original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved accuracy of time measurements however, this is out of scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-ified version is the instance data area of the subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should then be overridden.&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets also belong to the ''Text'' class, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of the ''Text'' class of course, is a toggle button. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but instead the ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains the &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to the ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes a nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with a label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed to it. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions for the application. There are five actions for running individual benchmarks and the sixth one for running all the tests and calculating the global result. Actions will be directly mapped to ''Application'' subclass methods. There is also one attribute connected with the &amp;quot;Large Data&amp;quot; button, it determines the sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at initialisation time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. GET-ability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template example and as such it has been generated with the [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must be of course created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
Five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on ''d-&amp;gt;LargeData'' switch variable. This variable is set with ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via notification. Then the status bar progress is cleared and a text is set to inform a user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may be not responding for user input for a time longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer, when the application window is active. Of course offloading processor intenstve task to a subprocess is a better solution in general case, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usablility problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with ''RAWFMTFUNC_STRING'' constant works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to a single benchmark one anyway. The difference is it runs all 5 tests accumulatig their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1071</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1071"/>
				<updated>2011-01-07T06:30:35Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* GUI Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in the benchmarks. The file ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides timing for the five functions performing all the benchmarks. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
The planned MUI interface should allow the user to run every benchmark separately or run all of them. There is also a ''-large'' option, which increases memory sizes for calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of the original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved accuracy of time measurements however, this is out of scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-ified version is the instance data area of the subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should then be overridden.&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets also belong to the ''Text'' class, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of the ''Text'' class of course, is a toggle button. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but instead the ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains the &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to the ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes a nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with a label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed to it. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions of the application. There are five actions of running individual benchmarks and the sixth one of running all the tests and calculate the global result. Actions will be directly mapped to an ''Application'' subclass methods. There is also one attribute connected with &amp;quot;Large Data&amp;quot; button, it determines sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at init time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. Gettability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template work and as such it has been generated with [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must be of course created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
Five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on ''d-&amp;gt;LargeData'' switch variable. This variable is set with ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via notification. Then the status bar progress is cleared and a text is set to inform a user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may be not responding for user input for a time longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer, when the application window is active. Of course offloading processor intenstve task to a subprocess is a better solution in general case, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usablility problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with ''RAWFMTFUNC_STRING'' constant works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to a single benchmark one anyway. The difference is it runs all 5 tests accumulatig their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1070</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1070"/>
				<updated>2011-01-07T06:22:53Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Code Inspection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in the benchmarks. The file ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides timing for the five functions performing all the benchmarks. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
The planned MUI interface should allow the user to run every benchmark separately or run all of them. There is also a ''-large'' option, which increases memory sizes for calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of the original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved accuracy of time measurements however, this is out of scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-ified version is the instance data area of the subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should then be overridden.&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets belong to ''Text'' class too, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of ''Text'' class of course, is a toggle one. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions of the application. There are five actions of running individual benchmarks and the sixth one of running all the tests and calculate the global result. Actions will be directly mapped to an ''Application'' subclass methods. There is also one attribute connected with &amp;quot;Large Data&amp;quot; button, it determines sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at init time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. Gettability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template work and as such it has been generated with [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must be of course created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
Five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on ''d-&amp;gt;LargeData'' switch variable. This variable is set with ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via notification. Then the status bar progress is cleared and a text is set to inform a user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may be not responding for user input for a time longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer, when the application window is active. Of course offloading processor intenstve task to a subprocess is a better solution in general case, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usablility problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with ''RAWFMTFUNC_STRING'' constant works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to a single benchmark one anyway. The difference is it runs all 5 tests accumulatig their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1069</id>
		<title>MUI Subclassing Tutorial: SciMark2 Port</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=MUI_Subclassing_Tutorial:_SciMark2_Port&amp;diff=1069"/>
				<updated>2011-01-07T06:15:50Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* The Application */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Application==&lt;br /&gt;
Many programming tutorials tend to bore readers with some useless examples. In this one a &amp;quot;real world&amp;quot; application will be ported to MorphOS and &amp;quot;MUI-fied&amp;quot;. The application is [http://math.nist.gov/scimark2/index.html SciMark 2]. SciMark is yet another CPU/memory benchmark. It performs some typical scientific calculations like Fast Fourier Transform, matrix LU decomposition, sparse matrix multiplication and so on. The benchmark measures mainly CPU speed at floating point calculations, cache efficiency and memory speed. Being written in Java initially, it has been rewritten in C (and in fact in many other languages). The C source is available on the [http://math.nist.gov/scimark2/download_c.html project homepage].&lt;br /&gt;
&lt;br /&gt;
The source uses only the pure ANSI C standard, so it is easily compilable on MorphOS using the provided ''Makefile''. One has just to replace the ''$CC = cc'' line to ''$CC = gcc'', to match the name of the MorphOS compiler. As a result, a typical shell-based application is obtained. Here are example results for a Pegasos 2 machine with G4 processor:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_noopt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Not very impressive in fact. This is because no optimizaton flags are passed to the compiler in the makefile. They can be added by inserting the line ''$CFLAGS = -O3'' below the ''$CC = gcc'' line. Let's also link with ''libnix'' (a statically linked unix environment emulation, see [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C.2B.2B_Libraries|Standard C and C++ Libraries]]) by adding ''-noixemul'' to ''CFLAGS'' and ''LDFLAGS''. After rebuilding the program and running it again the results are significantly improved (the program has been compiled with GCC 4.4.4 from the official SDK).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File: scimark_cli_opt.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This shows how important optimization of the code is, especially for computationally intensive programs. Optimized code is '''more than 4 times faster'''!&lt;br /&gt;
&lt;br /&gt;
==Code Inspection==&lt;br /&gt;
The original source code is well modularized. Five files: ''FFT.c'', ''LU.c'', ''MonteCarlo.c'', ''SOR.c'' and ''SparseCompRow.c'' implement the five of single benchmarks. Files ''array.c'' and ''Random.c'' contain auxiliary functions used in benchmarks. File ''Stopwatch.c'' implements time measurement. An important file ''kernel.c'' gathers all the above and provides five functions performing complete benchmarks with timing. Finally ''scimark2.c'' contains the ''main()'' function and implements the shell interface.&lt;br /&gt;
&lt;br /&gt;
A planned MUI interface should allow to run every benchmark separately and run all of them. There is also ''-large'' option, which increases memory sizes of calculated problems, so they do not fit into the processor cache. A general rule of porting is that as few files as possible should be modified. The rule makes it easier to upgrade the port when a new version of original program is released. In the case of SciMark, only one file, ''scimark2.c'' has to be replaced. An advanced port may also replace ''Stopwatch.c'' with code using ''timer.device'' directly for improved time measurements accuracy, this is out of scope of this tutorial however.&lt;br /&gt;
&lt;br /&gt;
A closer look at &amp;quot;scimark2.c&amp;quot; reveals that there is a ''Random'' object (a structure defined in &amp;quot;Random.h&amp;quot;), which is required for all the benchmarks. In the original code it is created with ''new_Random_seed()'' at the program start and disposed with ''delete_Random()'' at exit. The best place for it in the MUI-fied version is the instance data area of subclassed ''Application'' class. Then it can be created in ''OM_NEW()'' of the class and deleted in ''OM_DISPOSE()''. These two methods should be overridden then.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==GUI Design==&lt;br /&gt;
[[File:scimark_gui.png|left]] Of course there is no one and only proper GUI design for SciMark. A simple design, using a limited set of MUI classes is shown on the left. There are five buttons for individual benchmarks and one for running all of them. All these buttons are instances of the ''Text'' class. On the right there are gadgets for displaying benchmark results. These gadgets belong to ''Text'' class too, just having different attributes. The &amp;quot;Large Data&amp;quot; button, of ''Text'' class of course, is a toggle one. Surprisingly the status bar (displaying &amp;quot;Ready.&amp;quot;) is not an instance of the ''Text'' class, but ''Gauge'' class. Then it will be able to display a progress bar when running all five tests. Spacing horizontal bars above the &amp;quot;All Benchmarks&amp;quot; button are instances of the ''Rectangle'' class. There are also three invisible objects of the ''Group'' class. The first is a vertical, main group, being the root object of the window. It contains two sub-groups. The upper one is the table group with two columns and contains all the benchmark buttons and result display gadgets. The lower group contains &amp;quot;Large Data&amp;quot; toggle button and the status bar.&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with GUI design is just to copy the &amp;quot;Hello World&amp;quot; [[&amp;quot;Hello world!&amp;quot; in MUI|example]]. Then MUI objects may be added to ''build_gui()'' function. The [http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.c modified example] is ready to compile and run. It is not a complete program of course, just a GUI model without any functionality added.&lt;br /&gt;
&lt;br /&gt;
A quick view into the ''build_gui()'' function reveals that it does not contain all the GUI code. Code for some subobjects is placed in functions called from the main ''MUI_NewObject()''. Splitting the GUI building function into many subfunctions has a few important advantages:&lt;br /&gt;
* Improved code readability and easier modifications. A single ''MUI_NewObject()'' call gets longer and longer quickly as the project evolves. Editing a large function spanning over a few screens is uncomfortable. Adding and removing GUI objects in such a function becomes nightmare even with indentation used consequently. On the other hand the function can have 10 or more indentation levels, which makes it hard to read as well.&lt;br /&gt;
* Code size reduction. Instead of writing very similar code multiple times, for example buttons with different labels, a subroutine may be called with label as an argument.&lt;br /&gt;
* Debugging. It happens sometimes that MUI refuses to create the application object because of some buggy tags or values passed. If the main ''MUI_NewObject()'' call is split into subfunctions, it is easy to isolate the buggy object by inserting some ''Printf()''-s in subfunctions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
The SciMark GUI just designed, defines six actions of the application. There are five actions of running individual benchmarks and the sixth one of running all the tests and calculate the global result. Actions will be directly mapped to an ''Application'' subclass methods. There is also one attribute connected with &amp;quot;Large Data&amp;quot; button, it determines sizes of problems solved by benchmarks. Methods do not need any parameters, so there is no need to define method messages. An attribute may be applicable at init time (in the object constructor), may be also settable (needs ''OM_SET()'' [[Overriding OM_SET()|method overriding]]) and gettable (needs ''OM_GET()'' [[Overriding OM_GET()|method overriding]]). Our new attribute, named ''APPA_LargeData'' in the code only needs to be settable. In the constructor it can be implicitly set to ''FALSE'', as the button is switched off initially. Gettability is not needed, because this attribute will be used only inside the ''Application'' subclass.&lt;br /&gt;
&lt;br /&gt;
It is recommended that every subclass in the application is placed in a separate source file. It helps to keep code modularity and also allows for [[Short BOOPSI Overview#Classes|hiding class private data]]. This requires writing a makefile, but one is needed anyway, as the original SciMark code consists of multiple files. Implementing the design directions discussed above a [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.h class header file] and [http://krashan.ppa.pl/morphzone_tutorials/scimark2_application.c class code] can be written. The class still does nothing, just implements six empty methods and overrides ''[[Overriding OM_SET()|OM_SET()]]'', ''[[Overriding Constructors|OM_NEW()]]'' and ''[[Overriding Destructors|OM_DISPOSE()]]''. In fact it is a boring template work and as such it has been generated with [http://downloads.morphzone.org/find.php?find=chocolatecastle ChocolateCastle] template generator. Unfortunately ChocolateCastle is still beta, so files had to be tweaked manually after generation.&lt;br /&gt;
&lt;br /&gt;
The next step in the application design is to connect methods and attributes with GUI elements using [[Event Driven Programming, Notifications#Notifications in MUI|notifications]]. Notifications must be of course created after both source and target object are created. In the SciMark code they are just set up after executing ''build_gui()''. All the six action buttons have very similar notifications, so only one is shown here:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_FFT, App), MUIM_Notify, MUIA_Pressed, FALSE,&lt;br /&gt;
  App, 1, APPM_FastFourierTransform);&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Large Data&amp;quot; button has a notification setting the corresponding attribute:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(findobj(OBJ_BUTTON_LDATA, App), MUIM_Notify, MUIA_Selected, MUIV_EveryTime,&lt;br /&gt;
  App, 3, MUIM_Set, APPA_LargeData, MUIV_TriggerValue);&lt;br /&gt;
&lt;br /&gt;
Notified objects are accessed with [[Locating Objects in the Object Tree|dynamic search]] (the ''findobj()'' macro), which saves from defining global variables for all of them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementing Functionality==&lt;br /&gt;
Five methods implementing single SciMark benchmarks are very similar, so only one, running the Fast Fourier Transform has been shown:&lt;br /&gt;
&lt;br /&gt;
 IPTR ApplicationFastFourierTransform(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ApplicationData *d = INST_DATA(cl, obj);&lt;br /&gt;
   double result;&lt;br /&gt;
   LONG fft_size;&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;LargeData) fft_size = LG_FFT_SIZE;&lt;br /&gt;
   else fft_size = FFT_SIZE;&lt;br /&gt;
 &lt;br /&gt;
   SetAttrs(findobj(OBJ_STATUS_BAR, obj),&lt;br /&gt;
     MUIA_Gauge_InfoText, (LONG)&amp;quot;Performing Fast Fourier Transform test...&amp;quot;,&lt;br /&gt;
     MUIA_Gauge_Current, 0,&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 &lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, &amp;quot;&amp;quot;);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, TRUE);&lt;br /&gt;
   result = kernel_measureFFT(fft_size, RESOLUTION_DEFAULT, d-&amp;gt;R);&lt;br /&gt;
   NewRawDoFmt(&amp;quot;%.2f MFlops (N = %ld)&amp;quot;, RAWFMTFUNC_STRING, d-&amp;gt;Buf, result, fft_size);&lt;br /&gt;
   set(findobj(OBJ_RESULT_FFT, obj), MUIA_Text_Contents, d-&amp;gt;Buf);&lt;br /&gt;
   set(obj, MUIA_Application_Sleep, FALSE);&lt;br /&gt;
   set(findobj(OBJ_STATUS_BAR, obj), MUIA_Gauge_InfoText, &amp;quot;Ready.&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code uses [[Locating Objects in the Object Tree|dynamic object tree search]] for accessing MUI objects.&lt;br /&gt;
&lt;br /&gt;
The method sets the benchmark data size first, based on ''d-&amp;gt;LargeData'' switch variable. This variable is set with ''APPA_LargeData'' attribute, which in turn is bound to the &amp;quot;Large Data&amp;quot; button via notification. Then the status bar progress is cleared and a text is set to inform a user what is being done. The result textfield for the benchmark is cleared as well.&lt;br /&gt;
&lt;br /&gt;
The next step is to put the application in the &amp;quot;busy&amp;quot; state. It should be always done, when the application may be not responding for user input for a time longer than, let's say half a second. Setting ''MUIA_Application_Sleep'' to ''TRUE'' locks the GUI and displays the busy mouse pointer, when the application window is active. Of course offloading processor intenstve task to a subprocess is a better solution in general case, but for a benchmark it makes little sense. A user has to wait for the benchmark result anyway before doing anything else, like starting another benchmark. The only usablility problem is that a benchmark can't be stopped before it finishes. Let's leave it as is for now, for a benchmark, where the computer is expected to use all its computing power for benchmarking, a few seconds of GUI being unresponsive is not such a big problem.&lt;br /&gt;
&lt;br /&gt;
The next line of code runs the benchmark, by calling ''kernel_measureFFT()'' function from the original SciMark code. After the benchmark is done, the result is formatted and displayed in the result field using ''NewRawDoFmt()'', which is a low-level string formatting function from ''exec.library'' and with ''RAWFMTFUNC_STRING'' constant works just like ''sprintf()''. It uses a fixed buffer of 128 characters (which is much more than needed, but adds a safety margin) located in the object instance data. Unsleeping the application and setting status bar text to &amp;quot;Ready.&amp;quot; ends the method.&lt;br /&gt;
&lt;br /&gt;
The ''APPM_AllBenchmarks()'' method code is longer so it is not repeated here. The method is very similar to a single benchmark one anyway. The difference is it runs all 5 tests accumulatig their results in a table. It also updates the progress bar after every benchmark. Finally it calculates a mean score and displays it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Final Port==&lt;br /&gt;
[http://krashan.ppa.pl/morphzone_tutorials/scimark2_mui.lha The complete source of SciMark2 MUI port]&lt;br /&gt;
&lt;br /&gt;
The program may be built by running ''make'' in the source directory.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Subclassing_Application_Class&amp;diff=1068</id>
		<title>Subclassing Application Class</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Subclassing_Application_Class&amp;diff=1068"/>
				<updated>2011-01-07T06:10:16Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
Every MUI application is (or at least should be) an event driven one. This means the application provides a set of actions, which may be triggered with user activity (like using the mouse and keyboard). The straightforward way of implementing this set of actions is to implement it as a set of methods added to some MUI object. For simple programs, the best candidate for adding such methods is the master ''Application'' object. More complex programs (for example ones using a multi-document interface) may add actions to other classes, for example the ''Window'' class.&lt;br /&gt;
&lt;br /&gt;
Why methods? Implementing actions as methods has many advantages:&lt;br /&gt;
* Methods may be used directly as notification actions. It saves a programmer from using hook tricks or cluttering the main loop with lots of ''ReturnID'' values.&lt;br /&gt;
* Methods may be coupled directly with scripting language interface (formerly known as ARexx interface) commands.&lt;br /&gt;
* Methods used in notifications are executed immediately in response to user actions. No delay is introduced by the main loop (especially if it is not empty).&lt;br /&gt;
* A notification triggering attribute value may be [[Event Driven Programming, Notifications#Reusing Triggering Value|passed directly]] to a method as its parameter. &lt;br /&gt;
* Using methods improves code modularity and object encapsulation. Functionality meant to be handled in the scope of an object is handled in its method, without the code spreading across the project.&lt;br /&gt;
&lt;br /&gt;
In a well designed MUI program, all program actions and functionality are implemented as methods and the program internal state is stored as a set of attributes and internal application instance data fields. An example of such a program is discussed throughly in the [[MUI Subclassing Tutorial: SciMark2 Port]] article.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Overriding_OM_GET()&amp;diff=1067</id>
		<title>Overriding OM GET()</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Overriding_OM_GET()&amp;diff=1067"/>
				<updated>2011-01-07T06:05:14Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The ''OM_GET()'' method, used for getting an attribute from an object, receives an opGet structure as its message. The structure is defined in the ''&amp;lt;intuition/classusr.h&amp;gt;'' header file:&lt;br /&gt;
&lt;br /&gt;
 struct opGet&lt;br /&gt;
 {&lt;br /&gt;
   ULONG  MethodID;           /* always OM_GET (0x104) */&lt;br /&gt;
   ULONG  opg_AttrID;&lt;br /&gt;
   ULONG *opg_Storage;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Unlike ''[[Overriding OM_SET()|OM_SET()]]'', this method handles only one attribute at a time. The attribute is placed in the ''opg_AttrID'' field. The field ''opg_Storage'' is a '''pointer''' to a place where the attribute value should be stored. It is defined as a pointer to ULONG, but it may point to anything (for example to some larger structure). It allows for passing attributes not fitting in a 32-bit variable. Because ''OM_GET()'' does not have a taglist iteration loop, its implementation is simple:&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassGet(Class *cl, Object *obj, struct opGet *msg)&lt;br /&gt;
 {&lt;br /&gt;
   switch (msg-&amp;gt;opg_AttrID)&lt;br /&gt;
   {&lt;br /&gt;
     case Some_Integer_Tag:&lt;br /&gt;
       *msg-&amp;gt;opg_Storage = /* value of the tag */;&lt;br /&gt;
     return TRUE;&lt;br /&gt;
 &lt;br /&gt;
     case Some_String_Tag:&lt;br /&gt;
       *(char**)msg-&amp;gt;opg_Storage = &amp;quot;a fixed string value&amp;quot;;&lt;br /&gt;
     return TRUE;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   return DoSuperMethodA(cl, obj, (Msg)msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The implementation consists of a ''switch'' statement with ''cases'' for all recognized attributes. If an attribute is recognized, the method should return ''TRUE''. It is very important, as [[Event Driven Programming, Notifications#Notifications in MUI|MUI notifications]] rely on OM_GET() and will not work on the attribute if ''TRUE'' is not returned. Unknown attributes are passed to the superclass. The ''DoSuperMethodA()'' call may be alternatively placed as the ''default'' clause of the ''switch'' statement. It is important that ''msg-&amp;gt;opg_Storage'' is '''dereferenced''' when storing the attribute value. If the value type is not integer, a typecast is needed. For a value type ''T'', the dereferencing combined with typecast is denoted as ''*(T*)''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1066</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1066"/>
				<updated>2011-01-07T06:00:00Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* The Old And The New */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for ''include:'' and, if your system already assigns ''include:'' to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my ''S:user-startup'' after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with ''objdump'' although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing ''objdump'' not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
''objdump'' can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with ''vasm'' as before but note that the resulting object file is no longer executable.  To make this object executable, ''vlink'' is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, ''-lamiga'' refers to the ''libamiga.a'' file that ''vlink'' knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above ''vlink'' command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''-s''' strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
'''-P&amp;lt;symbol&amp;gt;''' preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for ''vlink'' and other programs installed with ''vbcc''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Overriding_OM_SET()&amp;diff=1065</id>
		<title>Overriding OM SET()</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Overriding_OM_SET()&amp;diff=1065"/>
				<updated>2011-01-07T05:57:01Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' method receives an ''opSet'' structure as its message. The structure is defined in the ''&amp;lt;intuition/classusr.h&amp;gt;'' header.&lt;br /&gt;
&lt;br /&gt;
 struct opSet&lt;br /&gt;
 {&lt;br /&gt;
   ULONG              MethodID;            /* always OM_SET (0x103) */&lt;br /&gt;
   struct TagItem    *ops_AttrList;&lt;br /&gt;
   struct GadgetInfo *ops_GInfo;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The most important field is ''ops_AttrList''. It is a pointer to a [[Taglists|taglist]] containing attributes and values to be set. The ''ops_GInfo'' field is an obsolete legacy thing and is not used by modern components like MUI or Reggae. The method implementation should iterate the taglist and set all attributes recognized. The operation of setting an attribute may be just setting some field in an object instance data, it may also trigger some actions (like for example object redrawing). It is recommended however that complex actions are implemented as methods rather than attribute changes. A reference implementation of ''OM_SET()'' may look like this:&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassSet(Class *cl, Object *obj, struct opSet *msg)&lt;br /&gt;
 {&lt;br /&gt;
   struct TagItem *tag, *tagptr;&lt;br /&gt;
   IPTR tagcount = 0;&lt;br /&gt;
 &lt;br /&gt;
   tagptr = msg-&amp;gt;ops_AttrList;&lt;br /&gt;
 &lt;br /&gt;
   while ((tag = '''NextTagItem'''(&amp;amp;tagptr)) != NULL)&lt;br /&gt;
   {&lt;br /&gt;
     switch (tag-&amp;gt;ti_Tag)&lt;br /&gt;
     {&lt;br /&gt;
       case SOME_TAG:&lt;br /&gt;
         /* attribute setting actions for SOME_TAG */&lt;br /&gt;
         tagcount++;&lt;br /&gt;
       break;&lt;br /&gt;
 &lt;br /&gt;
       /* more tags here */&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   tagcount += '''DoSuperMethodA'''(cl, obj, (Msg)msg);&lt;br /&gt;
   return tagcount;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The taglist iteration is done with the ''NextTagItem()'' function from the utility.library. The function returns a pointer to the next tag each time it is called and keeps the current position in ''tagptr''. The advantage of this function is automatic handling of special tag values (''TAG_MORE'', ''TAG_IGNORE'', ''TAG_SKIP''), they are not returned, but their actions are performed instead.&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' function returns the total number of recognized tags. It is implemented with ''tagcounter''. It gets incremented on every tag recognized and finally the number of tags recognized by superclass(es) is added.&lt;br /&gt;
&lt;br /&gt;
Common bugs in ''OM_SET()'' implementation are: ignoring tag counting and calling the super method in the ''default'' case of a ''switch'' statement. The second bug causes the supermethod to be called multiple times, once for every tag not handled by the subclass.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;In some rare cases a subclass may want to override an attribute completely, so it is not passed to superclasses. This can be done by replacing the tag (not value!) by ''TAG_IGNORE''. There is one caveat however. In most cases in C and C++, the taglist is built dynamically on the stack from variable arguments of a function like ''SetAttrs()''. It is possible however, that a taglist is a static object (for example a global one, or created in an allocated chunk of free memory). In this case changing a tag is a '''permanent''' operation, which may have unexpected results. This remark also applies for changing a value of a tag before passing it to a superclass. A safe solution is to clone the taglist with the ''CloneTagItems()'' function from the ''utility.library''. Then changes are made in the copy and this copy is passed to the superclass. The copy is then freed with ''FreeTagItems()''. The disadvantage of this solution is that cloning a taglist may fail due to lack of free memory and this possibility must be handled somehow.&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Overriding_Destructors&amp;diff=1064</id>
		<title>Overriding Destructors</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Overriding_Destructors&amp;diff=1064"/>
				<updated>2011-01-07T05:50:46Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The only task of a destructor is freeing resources allocated by the constructor and other methods (some resources may be allocated on-demand only). In any case the destructor must leave the object in the same state as right after ''DoSuperMethod()/DoSuperNew()'' in the constructor. After that the destructor calls a super class destructor. The destructor receives an empty message.&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassDispose(Class *cl, Object *obj, Msg msg)&lt;br /&gt;
 {&lt;br /&gt;
   struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);&lt;br /&gt;
 &lt;br /&gt;
   if (d-&amp;gt;ResourceA) FreeResourceA();&lt;br /&gt;
   if (d-&amp;gt;ResourceB) FreeResourceB();&lt;br /&gt;
   if (d-&amp;gt;ResourceC) FreeResourceC();&lt;br /&gt;
   return DoSuperMethodA(cl, obj, msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The example destructor follows the example of the constructor in the [[Overriding Constructors]] article. Three resources obtained in the constructor are freed here. The destructor is also prepared for a partially constructed object, every resource is checked against ''NULL'' before freeing. If for some type of resource NULL is a valid handle, an additional flag may be added to the object instance data area.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Overriding_Constructors&amp;diff=1063</id>
		<title>Overriding Constructors</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Overriding_Constructors&amp;diff=1063"/>
				<updated>2011-01-07T05:45:38Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Small typo and readability fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objects without child objects==&lt;br /&gt;
&lt;br /&gt;
An object constructor (''OM_NEW()'' method), takes the same message structure ''opSet'' as the ''[[Overriding OM_SET()|OM_SET()]]'' method. The message contains the ''ops_AttrList'' field, being a pointer to a [[Taglists|taglist]] containing the initial object's attributes. Implementation of a constructor for an object without child objects is simple. The superclass constructor is called first, then, if it succeeds, the constructor initializes object instance data, allocates resources needed and sets initial values of attributes from tags passed via ''ops_AttrList''.&lt;br /&gt;
&lt;br /&gt;
A rule of thumb when overriding constructors is to '''never leave a half-constructed object'''. The constructor should either return a fully constructed object, or fail completely, freeing all successfully obtained resources. This is important if the object obtains more than one resource and any of the resource allocation has failed (for example allocating a big chunk of memory or opening a file). An example implementation below obtains three resources: ''A'', ''B'' and ''C'':&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassNew(Class *cl, Object *obj, struct opSet *msg)&lt;br /&gt;
 {  &lt;br /&gt;
   if (obj = DoSuperMethodA(cl, obj, (Msg)msg))&lt;br /&gt;
   {&lt;br /&gt;
     struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);&lt;br /&gt;
 &lt;br /&gt;
     if ((d-&amp;gt;ResourceA = ObtainResourceA()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceB = ObtainResourceB()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceC = ObtainResourceC())&lt;br /&gt;
     {&lt;br /&gt;
       return (IPTR)obj;    /* success */&lt;br /&gt;
     }&lt;br /&gt;
     else CoerceMethod(cl, obj, OM_DISPOSE);&lt;br /&gt;
   }&lt;br /&gt;
   return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If the object destructor frees resources  ''A'', ''B'' and ''C'' (which would be logical considering the constructor allocates them), the cleanup job may be delegated to the destructor. It requires however, that the destructor must be prepared for destruction of a not fully constructed object. It can't assume all three resources have been allocated, so it should check every resource pointer against ''NULL'' before calling a freeing function. The destructor also takes care of calling a superclass destructor when resources are freed. See [[Overriding Destructors]] for some destructor example code and explanation.&lt;br /&gt;
&lt;br /&gt;
The only question remaining is what ''CoerceMethod()'' does and why it is used instead of a plain ''DoMethod()''? The ''CoerceMethod()'' call works exactly the same as ''DoMethod()'', but performs '''method coercion''' by a forced call to the dispatcher of the class specified as the first argument instead of the dispatcher of the object's true class. It makes a difference, when the class in question is later subclassed. The flowchart below explains the problem:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Coercemethod.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The class ''B'' on the diagram is a subclass of the class ''A'' and similarly, the class ''C'' is a subclass of ''B''. Let's assume an object of the class ''C'' is being constructed. As every constructor calls the superclass first, the call goes up to ''rootclass'' (the root of all BOOPSI classes) first. Then going down the class tree, every class constructor allocates its resources. Unfortunately the constructor of class ''A'' has been unable to allocate one of its resources and decided to fail. If it had just called ''DoMethod(obj, OM_DISPOSE)'' it will unnecessarily execute destructors in classes ''B'' and ''C'', while constructors in these classes have been not yet fully executed. Even if these destructors can cope with this, calling them is superfluous. With the ''CoerceMethod()'' the destructor in the class ''A'' is called directly. Then class ''A'' constructor returns NULL, which causes constructors in classes ''B'' and ''C'' to fail immediately without resource allocation attempts.&lt;br /&gt;
&lt;br /&gt;
==Objects with child objects==&lt;br /&gt;
&lt;br /&gt;
While retaining the same principles, the constructor of an object with subobjects is designed a bit differently. The most commonly subclassed classes able to have child objects are ''Application'', and ''Group''. The ''Window'' class is also often subclassed in a similar way. While a ''Window'' object can have only one child, specified by ''MUIA_Window_RootObject'', this child often has multiple subobjects. The constructor should create its child objects first, then insert them into the ''ops_AttrList'' [[Taglists|taglist]] and call the superclass constructor. If it succeeds, then resources may be allocated if needed. As any of the three constructor stages may fail, proper handling of errors becomes complicated. Also inserting objects created into the taglist as values of child tags (like ''MUIA_Group_Child'') is cumbersome. Fortunately one can use the ''DoSuperNew()'' function, which merges the creation of subobjects and the calling of the superclass into one operation. It also provides automatic handling of failed child object construction. An example below is a constructor for a ''Group'' subclass putting two ''Text'' objects in the group.&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassNew(Class *cl, Object *obj, struct opSet *msg)&lt;br /&gt;
 {  &lt;br /&gt;
   if (obj = DoSuperNew(cl, obj,&lt;br /&gt;
     MUIA_Group_Child, MUI_NewObject(MUIC_Text,&lt;br /&gt;
       /* attributes for the first subobject */&lt;br /&gt;
     TAG_END),&lt;br /&gt;
     MUIA_Group_Child, MUI_NewObject(MUIC_Text,&lt;br /&gt;
       /* attributes for the second subobject */&lt;br /&gt;
     TAG_END),&lt;br /&gt;
   TAG_MORE, msg-&amp;gt;ops_AttrList)) &lt;br /&gt;
   {&lt;br /&gt;
     struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);&lt;br /&gt;
 &lt;br /&gt;
     if ((d-&amp;gt;ResourceA = ObtainResourceA()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceB = ObtainResourceB()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceC = ObtainResourceC())&lt;br /&gt;
     {&lt;br /&gt;
       return (IPTR)obj;    /* success */&lt;br /&gt;
     }&lt;br /&gt;
     else CoerceMethod(cl, obj, OM_DISPOSE);&lt;br /&gt;
   }&lt;br /&gt;
   return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
An important thing to observe is the fact, that ''DoSuperNew()'' '''merges''' the taglist passed to the constructor via the message ''ops_AttrList'' field and the one specified in the function arguments list. It is done with a special ''TAG_MORE'' tag, which directs a taglist iterator (like ''NextTagItem()'' function) to jump to another taglist pointed by the value of this tag. Taglist merging allows for modifying the object being constructed with tags passed to ''NewObject()'', for example adding a frame or background to the group in the above example.&lt;br /&gt;
&lt;br /&gt;
The automatic handling of failed child objects works in the following way: when a subobject fails, its constructor returns ''NULL''. This ''NULL'' value is then inserted as the value of a &amp;quot;child&amp;quot; tag (''MUIA_Group_Child'') in the example. All MUI classes able to have child objects are designed in a way that:&lt;br /&gt;
* the constructor fails if any &amp;quot;child&amp;quot; tag has a ''NULL'' value,&lt;br /&gt;
* the constructor disposes any successfully constructed child objects before exiting.&lt;br /&gt;
Finally ''DoSuperNew()'' returns ''NULL'' as well. This design ensures that in case of any fail while building the application, all objects created are disposed and there are no orphaned ones.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Overriding_Constructors&amp;diff=1062</id>
		<title>Overriding Constructors</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Overriding_Constructors&amp;diff=1062"/>
				<updated>2011-01-07T05:36:33Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Small typos and readability changes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objects without child objects==&lt;br /&gt;
&lt;br /&gt;
An object constructor (''OM_NEW()'' method), takes the same message structure ''opSet'' as the ''[[Overriding OM_SET()|OM_SET()]]'' method. The message contains the ''ops_AttrList'' field, being a pointer to a [[Taglists|taglist]] containing the initial object's attributes. Implementation of a constructor for an object without child objects is simple. The superclass constructor is called first, then, if it succeeds, the constructor initializes object instance data, allocates resources needed and sets initial values of attributes from tags passed via ''ops_AttrList''.&lt;br /&gt;
&lt;br /&gt;
A rule of thumb when overriding constructors is to '''never leave a half-constructed object'''. The constructor should either return a fully constructed object, or fail completely, freeing all successfully obtained resources. This is important if the object obtains more than one resource and any of the resource allocation has failed (for example allocating a big chunk of memory or opening a file). An example implementation below obtains three resources: ''A'', ''B'' and ''C'':&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassNew(Class *cl, Object *obj, struct opSet *msg)&lt;br /&gt;
 {  &lt;br /&gt;
   if (obj = DoSuperMethodA(cl, obj, (Msg)msg))&lt;br /&gt;
   {&lt;br /&gt;
     struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);&lt;br /&gt;
 &lt;br /&gt;
     if ((d-&amp;gt;ResourceA = ObtainResourceA()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceB = ObtainResourceB()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceC = ObtainResourceC())&lt;br /&gt;
     {&lt;br /&gt;
       return (IPTR)obj;    /* success */&lt;br /&gt;
     }&lt;br /&gt;
     else CoerceMethod(cl, obj, OM_DISPOSE);&lt;br /&gt;
   }&lt;br /&gt;
   return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If the object destructor frees resources  ''A'', ''B'' and ''C'' (which would be logical considering the constructor allocates them), the cleanup job may be delegated to the destructor. It requires however, that the destructor must be prepared for destruction of a not fully constructed object. It can't assume all three resources have been allocated, so it should check every resource pointer against ''NULL'' before calling a freeing function. The destructor also takes care of calling a superclass destructor when resources are freed. See [[Overriding Destructors]] for some destructor example code and explanation.&lt;br /&gt;
&lt;br /&gt;
The only question remaining is what ''CoerceMethod()'' does and why it is used instead of a plain ''DoMethod()''? The ''CoerceMethod()'' call works exactly the same as ''DoMethod()'', but performs '''method coercion''' by a forced call to the dispatcher of the class specified as the first argument instead of the dispatcher of the object's true class. It makes a difference, when the class in question is later subclassed. The flowchart below explains the problem:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Coercemethod.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The class ''B'' on the diagram is a subclass of the class ''A'' and similarly, the class ''C'' is a subclass of ''B''. Let's assume an object of the class ''C'' is being constructed. As every constructor calls the superclass first, the call goes up to ''rootclass'' (the root of all BOOPSI classes) first. Then going down the class tree, every class constructor allocates its resources. Unfortunately the constructor of class ''A'' has been unable to allocate one of its resources and decided to fail. If it had just called ''DoMethod(obj, OM_DISPOSE)'' it will unnecessarily execute destructors in classes ''B'' and ''C'', while constructors in these classes have been not yet fully executed. Even if these destructors can cope with this, calling them is superfluous. With the ''CoerceMethod()'' the destructor in the class ''A'' is called directly. Then class ''A'' constructor returns NULL, which causes constructors in classes ''B'' and ''C'' to fail immediately without resource allocation attempts.&lt;br /&gt;
&lt;br /&gt;
==Objects with child objects==&lt;br /&gt;
&lt;br /&gt;
While retaining the same principles, a constructor of object having subobjects is designed a bit differently. The most commonly subclassed classes able to have child objects are ''Application'', and ''Group''. The ''Window'' class is also often subclassed similar way. While a ''Window'' object can have only one child, specified by ''MUIA_Window_RootObject'', this child has multiple subobjects usually. The constructor should create its child objects first, then insert them into the ''ops_AttrList'' [[Taglists|taglist]] and call the superclass constructor. If it succeeds, then resources may be allocated if needed. As any of the three constructor stages may fail, proper handling of errors becomes complicated. Also inserting objects created into the taglist as values of child tags (like ''MUIA_Group_Child'') is cumbersome. Fortunately one can use the ''DoSuperNew()'' function, which merges subobjects creation and calling the superclass into one operation. It also provides automatic handling of failed child object construction. An example below is a constructor for a ''Group'' subclass putting two ''Text'' objects in the group.&lt;br /&gt;
&lt;br /&gt;
 IPTR MyClassNew(Class *cl, Object *obj, struct opSet *msg)&lt;br /&gt;
 {  &lt;br /&gt;
   if (obj = DoSuperNew(cl, obj,&lt;br /&gt;
     MUIA_Group_Child, MUI_NewObject(MUIC_Text,&lt;br /&gt;
       /* attributes for the first subobject */&lt;br /&gt;
     TAG_END),&lt;br /&gt;
     MUIA_Group_Child, MUI_NewObject(MUIC_Text,&lt;br /&gt;
       /* attributes for the second subobject */&lt;br /&gt;
     TAG_END),&lt;br /&gt;
   TAG_MORE, msg-&amp;gt;ops_AttrList)) &lt;br /&gt;
   {&lt;br /&gt;
     struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);&lt;br /&gt;
 &lt;br /&gt;
     if ((d-&amp;gt;ResourceA = ObtainResourceA()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceB = ObtainResourceB()&lt;br /&gt;
      &amp;amp;&amp;amp; (d-&amp;gt;ResourceC = ObtainResourceC())&lt;br /&gt;
     {&lt;br /&gt;
       return (IPTR)obj;    /* success */&lt;br /&gt;
     }&lt;br /&gt;
     else CoerceMethod(cl, obj, OM_DISPOSE);&lt;br /&gt;
   }&lt;br /&gt;
   return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
An important thing to observe is the fact, that ''DoSuperNew()'' '''merges''' the taglist passed to the constructor via the message ''ops_AttrList'' field and the one specified in the function arguments list. It is done with a special ''TAG_MORE'' tag, which direct a taglist iterator (like ''NextTagItem()'' function) to jump to another taglist pointed by the value of this tag. Taglist merging allows for modifying the object being constructed with tags passed to ''NewObject()'', for example adding a frame or background to the group in the above example.&lt;br /&gt;
&lt;br /&gt;
The automatic handling of failed child objects works in the following way: when a subobject fails, its constructor returns ''NULL''. This ''NULL'' value is then inserted as a value of a &amp;quot;child&amp;quot; tag (''MUIA_Group_Child'') in the example. All MUI classes able to have child objects are designed in a way that:&lt;br /&gt;
* the constructor fails if any &amp;quot;child&amp;quot; tag has ''NULL'' value,&lt;br /&gt;
* the constructor disposes any succesfully constructed child objects before exiting.&lt;br /&gt;
Finally ''DoSuperNew()'' returns ''NULL'' as well. This design ensures that in case of any fail while building the application, all objects created are disposed and there are no orphaned ones.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1061</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1061"/>
				<updated>2011-01-06T23:10:03Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for ''include:'' and, if your system already assigns ''include:'' to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my ''S:user-startup'' after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with ''objdump'' although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing ''objdump'' not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
''objdump'' can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with ''vasm'' as before but note that the resulting object file is no longer executable.  To make this object executable, ''vlink'' is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, ''-lamiga'' refers to the ''libamiga.a'' file that ''vlink'' knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above ''vlink'' command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''-s''' strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
'''-P&amp;lt;symbol&amp;gt;''' preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for ''vlink'' and other programs installed with ''vbcc''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1060</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1060"/>
				<updated>2011-01-06T23:08:00Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for ''include:'' and, if your system already assigns ''include:'' to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my ''S:user-startup'' after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with ''objdump'' although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing ''objdump'' not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
''objdump'' can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with ''vasm'' as before but note that the resulting object file is no longer executable.  To make this object executable, ''vlink'' is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, ''-lamiga'' refers to the ''libamiga.a'' file that ''vlink'' knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above ''vlink'' command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for ''vlink'' and other programs installed with ''vbcc''.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1059</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1059"/>
				<updated>2011-01-06T23:00:16Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as ''HelloWorld.s'' and open a shell window.  Change directory to where ''HelloWorld.s'' was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of ''HelloWorld.s'' in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of '''r0''' in some instruction operands will not always work as you might expect.  In these instructions, the actual content of '''r0''' is ignored and the result is based on the constant value zero instead.  For example, imagine that '''r0''' contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150'''  The result will actually be '''r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50'''  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1058</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1058"/>
				<updated>2011-01-06T22:53:37Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the '''@ha''' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The '''@h''' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1057</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1057"/>
				<updated>2011-01-06T22:50:35Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Small addition to @ha @l explanation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
'''@h''' '''@ha''' &amp;amp; '''@l''' attributes are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  The difference between '''@h''' and '''@ha''' is due to the common use of the '''addi''' (add immediate) instruction, which only takes a signed immediate value, to provide the lower 16 bits of a 32 bit constant - such as an address.  Sometimes these lower 16 bits will equate to a negative value and it is then that prior use of the ''@ha'' attribute will cause its immediate value to be adjusted to compensate.  These details are only resolved before execution, when the program is loaded.  The ''@h'' attribute just specifies the upper halfword of a 32 bit constant without regard for what follows.  While I'm banging on about such intricacies, the meaning of ''zero'' in ''load word and zero'' of the '''lwz''' instruction is that on 64 bit PPC processors, this instruction will load a 32 bit value from memory into the lower word of a 64 bit GPR and then clear (or zero) its upper word.  Something to consider when MorphOS is available on G5 class computers...  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like ''shorty'') it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
'Uh?' indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like ''shorty'' does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1056</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1056"/>
				<updated>2011-01-06T22:01:57Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  ''shorty.o'' was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a '''word'''.  But let's take a moment to have a look at the size of ''shorty.o''&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the '''-s''' 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than its object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of ''shorty''.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the ''objdump'' program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1055</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=1055"/>
				<updated>2011-01-06T21:58:01Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called ''shorty.o'' in ram: from the ''shorty.s'' source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=General_Rules_and_Purpose_of_Subclassing&amp;diff=1054</id>
		<title>General Rules and Purpose of Subclassing</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=General_Rules_and_Purpose_of_Subclassing&amp;diff=1054"/>
				<updated>2011-01-06T21:52:59Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Fixing minor typos and other small changes for readability.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Subclassing is one of the essential object oriented programming techniques. In MUI subclassing is used for the following purposes:&lt;br /&gt;
* Implementing program functionality as a set of methods. The ''Application'' class is usually used for this purpose.&lt;br /&gt;
* Customizing classes by writing methods intentionally left unimplemented (or having some default implementations) in standard  MUI classes. The most common example is the ''List'' class, but also the ''Numeric'' one and others.&lt;br /&gt;
* Writing custom drawn gadgets or areas. The ''Area'' class is subclassed in this case.&lt;br /&gt;
Regardless of the reason for subclassing, it is always done in the same way. A programmer must write new methods or override existing methods, create a dispatcher function, define an instance data structure (an empty one in some cases), then create the class. It is worth noting, subclassing MUI classes is done the same as subclassing [[Short_BOOPSI_Overview|BOOPSI ones]]. The only difference is that MUI provides its [[Short_BOOPSI_Overview#MUI_Extensions_to_BOOPSI|own functions]] for class creation and disposition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Object Data==&lt;br /&gt;
&lt;br /&gt;
Object data are stored in a memory area automatically allocated for every object created. The object data area is used for storing attribute values and for internal variables and buffers. This area is usually defined as a structure. Size of the area is passed to the ''MUI_CreateCustomClass()'' function. In a class hierarchy, every class may add its own contribution to the object data area. Unlike in C++, a class has no direct access to anything except its own data area. It can't access data defined in the superclass (In C++ it is possible that a field is declared as ''protected'' or ''public''). Object data defined in any of the superclasses may only be accessed using methods or attributes provided by these superclasses. &lt;br /&gt;
&lt;br /&gt;
Because of internal [[Short BOOPSI Overview|BOOPSI]] design, the size of the data instance area is limited to 64 kB. Large buffers should be allocated dynamically in OM_NEW() and freed in OM_DISPOSE(). The area data is always cleared to all zeros at object creation. If a class does not need any object instance data it can pass 0 as the area size to ''MUI_CreateCustomClass()''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Writing Methods==&lt;br /&gt;
A MUI method is just a plain C function, but with a partially fixed prototype.&lt;br /&gt;
&lt;br /&gt;
 IPTR ''MethodName''(Class *cl, Object *obj, ''MessageType'' *msg);&lt;br /&gt;
&lt;br /&gt;
The method return value may be either integer or pointer to anything. That is why it uses the ''IPTR'' type which means &amp;quot;integer big enough to hold a pointer&amp;quot;. In the current MorphOS it is just a 32-bit integer (the same as ''LONG''). If a method has no meaningful value to return, it can just return 0. Two first, fixed arguments are: pointer to the class and pointer to the object. The last one is a method message. When a method is being overridden, the type of message is determined by the superclass. For a new method, message type is defined by the programmer. Some methods may have empty messages (containing only a method identifier), in this case the third argument may be omitted.&lt;br /&gt;
&lt;br /&gt;
Most methods need access to the object instance data. To get a pointer to the data area, one uses the ''INST_DATA'' macro, defined in ''&amp;lt;intuition/classes.h&amp;gt;''. An example below shows the macro usage:&lt;br /&gt;
&lt;br /&gt;
 struct ObjData&lt;br /&gt;
 {&lt;br /&gt;
   LONG SomeVal;&lt;br /&gt;
   /* ... */&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 IPTR SomeMethod(Class *cl, Object *obj)&lt;br /&gt;
 {&lt;br /&gt;
   struct ObjData *d = (struct ObjData*)'''INST_DATA(cl, obj)''';&lt;br /&gt;
 &lt;br /&gt;
   d-&amp;gt;SomeVal = 14;&lt;br /&gt;
   /* ... */&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If a method is an overridden method from a superclass, it may want to perform the superclass method. There are no implicit super method calls in MUI. The superclass method must always be called explicitly with the ''DoSuperMethodA()'' call:&lt;br /&gt;
&lt;br /&gt;
 result = DoSuperMethodA(cl, obj, msg);&lt;br /&gt;
 result = DoSuperMethod(cl, obj, ''MethodID'', ...);&lt;br /&gt;
&lt;br /&gt;
The second form rebuilds the method message from variable arguments, and is used when the message is modified before calling the superclass method. The super method may be called in any place of the method, or may not be called at all. For MUI standard classes and methods, rules of calling super methods are described in the documentation and will be discussed later in this tutorial. For custom methods the question of calling a super method is up to the application programmer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Dispatcher==&lt;br /&gt;
A dispatcher function is a kind of jump table for methods. When any method is called on an object (with ''DoMethod()''), BOOPSI finds the dispatcher of the object's class and calls it. The dispatcher checks a method identifier, which is always the first field of any method message. Based on the identifier, a method is called. If a method is unknown to the class, the dispatcher should pass it to the superclass with the ''DoSuperMethod()'' call.&lt;br /&gt;
&lt;br /&gt;
The dispatcher is a kind of [[Hooks|hook]] function. It makes its calling convention independent of programming language. A disadvantage of this is that the dispatcher's arguments are passed in virtual M68k processor registers. This inconvenience allows support for legacy M68k software and also allows for native PowerPC classes to be used by M68k applications and old M68k classes to be used by native applications. Being a hook, a dispatcher needs an ''EmulLibEntry'' structure to be created and filled first. The structure is defined in  ''&amp;lt;emul/emulinterface.h&amp;gt;'' and acts as a data gate between PowerPC native code and the M68k emulator.&lt;br /&gt;
&lt;br /&gt;
 const struct EmulLibEntry ClassGate = {TRAP_LIB, 0, (void(*)(void))ClassDispatcher};&lt;br /&gt;
&lt;br /&gt;
Then the dispatcher is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 IPTR ClassDispatcher(void)&lt;br /&gt;
 {&lt;br /&gt;
   Class *cl = (Class*)REG_A0;&lt;br /&gt;
   Object *obj = (Object*)REG_A2;&lt;br /&gt;
   Msg msg = (Msg)REG_A1;&lt;br /&gt;
 &lt;br /&gt;
   /* ... */&lt;br /&gt;
&lt;br /&gt;
Arguments of the dispatcher are the same as arguments of a method. They are passed in virtual M680x0 processor address registers A0, A1 and A2 instead of being just arguments. The dispatcher's data gate is passed as an argument to ''MUI_CreateCustomClass()''. The data gate is used even when a native application calls a native dispatcher. It introduces some overhead, but it's negligible. Many programmers prefer to hide these details behind a set of preprocessor macros, such macros have not been used here however, for better understanding.&lt;br /&gt;
&lt;br /&gt;
The ''Msg'' type is a root type for all method messages. It defines a structure containing only the method identifier field (defined as ULONG). All following parameters have to keep the CPU stack aligned, as ''DoMethod()'' builds the message on the stack. It requires that every parameter is defined either as an ''IPTR'' or as a pointer.&lt;br /&gt;
&lt;br /&gt;
After receiving arguments the dispatcher checks the method identifier from the message and jumps to the respective method. It is usually implemented as a ''switch'' statement. If only a few methods are implemented, it may also be an ''if/if else'' cascade. Here is a typical example:&lt;br /&gt;
&lt;br /&gt;
 switch (msg-&amp;gt;MethodID)&lt;br /&gt;
 {&lt;br /&gt;
   case OM_NEW:            return MyClassNew(cl, obj, (struct opSet*)msg);&lt;br /&gt;
   case OM_DISPOSE:        return MyClassDispose(cl, obj, msg);&lt;br /&gt;
   case OM_SET:            return MyClassSet(cl, obj, (struct opSet*)msg);&lt;br /&gt;
   case OM_GET:            return MyClassGet(cl, obj, (struct opGet*)msg);&lt;br /&gt;
   case MUIM_Draw:         return MyClassDraw(cl, obj, (struct MUIP_Draw*)msg);&lt;br /&gt;
   case MUIM_AskMinMax:    return MyClassAskMinMax(cl, obj, (struct MUIP_AskMinMax*)msg);&lt;br /&gt;
   /* ... */&lt;br /&gt;
   default:                return DoSuperMethodA(cl, obj, msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
For every method a message pointer is typecast to a message structure of this particular method. Some programmers place the method's code inside the ''switch'' statement directly, especially if methods are short and only a few. In the example above, some methods of ''Area'' class are overridden. The naming scheme used for the method functions is just an example, there are no constraints on this. Although prefixing method function names with a class name has an advantage of avoiding name conflicts between custom classes if method functions are not declared as ''static''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Class Creation==&lt;br /&gt;
&lt;br /&gt;
Having all components done (methods, dispatcher, gate, object data structure) one can create a MUI class.&lt;br /&gt;
&lt;br /&gt;
 struct MUI_CustomClass *MyClass;&lt;br /&gt;
 &lt;br /&gt;
 MyClass = MUI_CreateCustomClass(NULL, MUIC_Area, NULL, sizeof(struct MyClassData),&lt;br /&gt;
  (APTR)&amp;amp;MyClassGate);&lt;br /&gt;
&lt;br /&gt;
The first argument is a library base if the created class is public. Writing MUI public classes will be covered later. Let's say for now, that public classes are implemented as shared libraries, so such a public class has a library base. For private classes this argument should always be ''NULL''. &lt;br /&gt;
&lt;br /&gt;
The next two arguments are used alternatively and specify the superclass. The superclass may be either private (referenced by pointer) or public (referenced by name). Public classes are usually subclassed, so the pointer is set to ''NULL'' as in the example. More complex projects may use multilevel subclassing and subclass their own private classes. In this case, a pointer to a private class is passed as the first argument and the second one is ''NULL''.&lt;br /&gt;
&lt;br /&gt;
The fourth argument defines the size of the object data area in bytes. In most cases object data area is defined as a structure, so using the ''sizeof()'' operator is the obvious way of determining the size. If the class does not need any per-object data, zero may be passed here.&lt;br /&gt;
&lt;br /&gt;
The last argument is an address of the data gate (''EmulLibEntry'' structure). Programmers experienced on M68k programming may notice that there is a difference &amp;amp;ndash; in M68k code only the dispatcher function address is used here. As mentioned above, seamless M68k code support requires that program execution passes through the data gate when going from system code to the dispatcher. That is why the data gate address is placed as this argument, then the data gate contains a real dispatcher address.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Class Disposition==&lt;br /&gt;
&lt;br /&gt;
A MUI class is disposed with a call to ''MUI_DeleteCustomClass()''.&lt;br /&gt;
&lt;br /&gt;
 if (MyClass) MUI_DeleteCustomClass(MyClass);&lt;br /&gt;
&lt;br /&gt;
Some conditions must be fulfilled before calling this function.&lt;br /&gt;
* Call it only if the class was successfully created. Calling it with a ''NULL'' class pointer is deadly (hence the checking for ''NULL'' in the example).&lt;br /&gt;
* Do not delete a class if it has any remaining subclasses or objects. The best practice is to create all classes before creating the application GUI and to dispose them after the final ''MUI_DisposeObject()'' of the main ''Application'' object. Classes should be deleted in the reversed order of creation. ''MUI_DeleteCustomClass()'' returns a boolean value. It is FALSE when a class cannot be deleted because of potentially orphaned subclasses or objects.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=893</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=893"/>
				<updated>2010-12-11T05:22:08Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: overlooked a bad path name in user-startup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: SYS:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=892</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=892"/>
				<updated>2010-12-11T05:20:10Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: fixed bad suggestion re: assign include: in user-startup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: SDK:GG/os-include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=888</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=888"/>
				<updated>2010-11-29T02:10:59Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* A Little Less Talk And A Little More Action Please */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/MorphOS-PPC-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Old-and-new.png&amp;diff=887</id>
		<title>File:Old-and-new.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Old-and-new.png&amp;diff=887"/>
				<updated>2010-11-26T21:20:10Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: uploaded a new version of &amp;quot;File:Old-and-new.png&amp;quot;:&amp;amp;#32;Fixing omitted description in diagram showing commented 68k and PPC instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram showing commented 68k and PPC instructions&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=886</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=886"/>
				<updated>2010-11-26T20:27:36Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Fixed a mistake in the source listing &amp;amp; added a paragraph.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/morphos-ppc-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets&lt;br /&gt;
.set	_LVOOpenLibrary,-552&lt;br /&gt;
.set	_LVOCloseLibrary,-414&lt;br /&gt;
.set	_LVOVPrintf,-954&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4&lt;br /&gt;
&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)&lt;br /&gt;
.set	reg_d0,0&lt;br /&gt;
.set	reg_d1,4&lt;br /&gt;
.set	reg_d2,8&lt;br /&gt;
.set	reg_d3,12&lt;br /&gt;
.set	reg_d4,16&lt;br /&gt;
.set	reg_d5,20&lt;br /&gt;
.set	reg_d6,24&lt;br /&gt;
.set	reg_d7,28&lt;br /&gt;
.set	reg_a0,32&lt;br /&gt;
.set	reg_a1,36&lt;br /&gt;
.set	reg_a2,40&lt;br /&gt;
.set	reg_a3,44&lt;br /&gt;
.set	reg_a4,48&lt;br /&gt;
.set	reg_a5,52&lt;br /&gt;
.set	reg_a6,56&lt;br /&gt;
.set	reg_a7,60&lt;br /&gt;
.set	EmulCallDirectOS,100&lt;br /&gt;
&lt;br /&gt;
# Stack frame offsets&lt;br /&gt;
.set	stack_pos0_caller_stack,0&lt;br /&gt;
.set	stack_pos1_callerLR,4&lt;br /&gt;
.set	stack_pos2_ExecBase,8&lt;br /&gt;
.set	stack_pos3_DosBase,12&lt;br /&gt;
.set	new_4_word_stack,16&lt;br /&gt;
&lt;br /&gt;
.text&lt;br /&gt;
&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl&lt;br /&gt;
&lt;br /&gt;
	li	r3,0&lt;br /&gt;
&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr&lt;br /&gt;
&lt;br /&gt;
.rodata&lt;br /&gt;
		#__abox__ is a special MorphOS symbol that will differentiate&lt;br /&gt;
__abox__:	#this program from other PPC executables that can run on MorphOS...&lt;br /&gt;
		#When linking, care should be taken to avoid stripping this symbol.&lt;br /&gt;
dosName:&lt;br /&gt;
.string	&amp;quot;dos.library&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
string1:&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
The commented version of HelloWorld.s in the downloadable source archive gives a brief description of why the '''mtctr''' (move to Count Register) &amp;amp; '''bctrl''' (branch to Count Register and link) instruction pair are used in preference to '''mtlr''' (move to Link Register) &amp;amp; '''blrl''' (branch to Link Register and link) - being that the latter pair can degrade performance optimisations of some PPC cpus.  However, the primary use of the Count Register is as a 32 bit loop counter that can be automatically decremented by certain branch instructions.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them: [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=885</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=885"/>
				<updated>2010-11-26T05:05:41Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Reorganising and adding content.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/morphos-ppc-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
''; vbcc MorphOS target needs include: to be assigned to somewhere''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
; vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  Note that while MorphOS 2.x system files are compiled as ELFs, they are also signed to prevent their use on MorphOS 1.x where they may not work.  This signing also has the effect of causing objdump not to recognise them as ELFs.  &lt;br /&gt;
&lt;br /&gt;
Objdump can be used to reveal a lot of interesting information about an ELF including listing any symbols and sections that are present as well as disassembling.  Be aware that, when disassembled, seemingly small programs can produce more output than the shell window's history buffer can hold so either redirect the output to a file or specify start and stop addresses to limit the output.  Having said that, none of the files generated so far in this tutorial are at risk of overwhelming the shell's history buffer when disassembled. &lt;br /&gt;
&lt;br /&gt;
''more content needed here''&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  The approach used will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary'''.  Remove or comment out the first three '''.set''' directives that define the library function offsets and assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the ''libamiga.a'' file that vlink knows to look for in ''vlibmos:''  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip all symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=884</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=884"/>
				<updated>2010-11-26T04:48:58Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Minor additions and other small edits.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  Alternatively, download this fully commented [http://aminet.net/dev/src/morphos-ppc-HelloWorld.lha source archive].  &lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.s and open a shell window.  Change directory to where HelloWorld.s was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  ''Hint: Have another look at the System V.4 register usage above.''&lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 when this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, this behaviour can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available online - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  This approach will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names and appending '@l' to the end so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary@l'''.  Assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the libamiga.a file that vlink knows to look for in vlibmos:  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-x discard local symbols from input file(s)&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.  &lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  &lt;br /&gt;
&lt;br /&gt;
''final part yet to come''&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=883</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=883"/>
				<updated>2010-11-26T04:35:58Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Very minor edit.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  ''A fully commented version will be made available for download soon.''&lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.p and open a shell window.  Change directory to where HelloWorld.p was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 and then this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, it can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available on the internet - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  This approach will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names and appending '@l' to the end so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary@l'''.  Assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the libamiga.a file that vlink knows to look for in vlibmos:  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-x discard local symbols from input file(s)&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.  &lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  &lt;br /&gt;
&lt;br /&gt;
''final part yet to come''&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=882</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=882"/>
				<updated>2010-11-26T04:24:07Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Removing unnecessary command line options.  Other minor edits.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2664 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with the -s 'strip all symbols' option, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -s -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos Library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  ''A fully commented version will be made available for download soon.''&lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.p and open a shell window.  Change directory to where HelloWorld.p was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 and then this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, it can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available on the internet - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  This approach will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names and appending '@l' to the end so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary@l'''.  Assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the libamiga.a file that vlink knows to look for in vlibmos:  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-x discard local symbols from input file(s)&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.  &lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  &lt;br /&gt;
&lt;br /&gt;
''final part yet to come''&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=881</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=881"/>
				<updated>2010-11-26T04:17:20Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Changing source file extension to one that is recognised by MorphOS.  Other minor edits.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as ''shorty.s''&lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.s has been saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an ELF formatted object file called shorty.o in ram: from the shorty.s source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2660 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with a few key options, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos Library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  ''A fully commented version will be made available for download soon.''&lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.p and open a shell window.  Change directory to where HelloWorld.p was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 and then this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, it can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available on the internet - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  This approach will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names and appending '@l' to the end so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary@l'''.  Assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the libamiga.a file that vlink knows to look for in vlibmos:  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-x discard local symbols from input file(s)&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.  &lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  &lt;br /&gt;
&lt;br /&gt;
''final part yet to come''&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=880</id>
		<title>An Introduction to MorphOS PPC Assembly</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=An_Introduction_to_MorphOS_PPC_Assembly&amp;diff=880"/>
				<updated>2010-11-24T14:52:37Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Article content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Jump In The Deep End And Compile Something Right Now==&lt;br /&gt;
&lt;br /&gt;
You could copy and paste but just entering the two lines below into a suitable text editor is probably quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.text&lt;br /&gt;
	blr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save as 'shorty.p'.  &lt;br /&gt;
&lt;br /&gt;
'''.text''' is an assembler directive - more about it later.  '''blr''' is one of many branch instructions.  This particular one means 'Branch to Link Register'.  When a program terminates, this is the last instruction to be executed and it causes the sequence of instruction execution to pass back to the calling program or environment (shell, Ambient etc).  Subroutines can also terminate with this instruction but, again, more about this later.  &lt;br /&gt;
&lt;br /&gt;
This is as good a time as any to ask if you've installed vbcc yet - if not, go and do it.  [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_bin_morphos.lha Download vbcc]&lt;br /&gt;
&lt;br /&gt;
Once vbcc is installed, open a shell window and change directory to where shorty.p is saved.  &lt;br /&gt;
&lt;br /&gt;
Enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:shorty.o shorty.p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells vasm to generate an elf formatted object file called shorty.o in ram: from the shorty.p source file.&lt;br /&gt;
&lt;br /&gt;
==Hello?  World's Shortest MorphOS Program - Or Is It?==&lt;br /&gt;
&lt;br /&gt;
There are times when a linker is needed to further process an object file to generate an executable - this isn't one of those times.  &lt;br /&gt;
&lt;br /&gt;
Go ahead and enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will appear as if nothing happens - but at least it happens very quickly.  However, something did happen.  shorty.o was identified as an executable program and loaded into memory where the cpu instruction execution sequence passed to it.  As mentioned above, the single '''blr''' instruction in this program caused the instruction execution sequence to pass directly back to where it was called from - in this case, the shell.  &lt;br /&gt;
&lt;br /&gt;
It may be of interest to know that all PPC instructions are four bytes long.  In PPC nomenclature, this length is known as a word.  But let's take a moment to have a look at the size of shorty.o&lt;br /&gt;
&lt;br /&gt;
Enter this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list ram:shorty.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2660 bytes?!  But this is typical for object files as they contain much additional information that is used in the process of debugging and linking.  Linking, particularly with a few key options, will generate an executable that is noticeably smaller.  &lt;br /&gt;
&lt;br /&gt;
Try entering this into the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -o ram:shorty ram:shorty.o&lt;br /&gt;
&lt;br /&gt;
list ram:shorty&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly generated executable is 328 bytes - much smaller than it's object file but what are those other 324 bytes doing there?  They are the ELF 'container' that holds the single, four byte instruction of shorty.  ELF stands for Executable and Linkable Format and it is used by MorphOS, AmigaOS4 and AROS - not to forget, Linux, UNIX, BSD and even video game consoles.  There is abundant information about this file format online but this topic will be discussed a little further when the use of the objdump program is introduced.&lt;br /&gt;
&lt;br /&gt;
==The Old And The New==&lt;br /&gt;
&lt;br /&gt;
Generally, in order to make a program that does something useful or to at least produce an observable result, it is necessary to use operating system library functions.  Despite the markedly different cpu family that MorphOS runs on compared to the 68k family used by the classic AmigaOS, MorphOS is largely compatible with AmigaOS.  This compatibility is reflected in a very similar API shared with AmigaOS and extends to using a MorphOS system structure as if it were the internal data and address registers of an actual 68k processor.  This is called the EmulHandle structure and it is always available through the PPC GPR2 register.  Also, as with 68k AmigaOS, the address of the Exec library base is always to be found at memory location 4.  Many aspects of the AmigaOS API fit closely to the features available in the 68k cpu and the following code comparison should illustrate how it is echoed in the PPC MorphOS API.  &lt;br /&gt;
&lt;br /&gt;
A common task performed during the initialisation of many programs - opening the Dos Library.  It is a particularly simple example of library usage but most functions follow this form.  &lt;br /&gt;
&lt;br /&gt;
[[File:Old-and-new.png]]&lt;br /&gt;
&lt;br /&gt;
@ha &amp;amp; @l are needed to specify the high and low halfwords of 32 bit immediate values because the fixed 32 bit size of PPC instructions does not allow enough space for an instruction opcode and additional 32 bits of data.  &lt;br /&gt;
&lt;br /&gt;
One could be forgiven for thinking that the PPC code snippet looks a little ungainly compared to the former.  Whereas every PPC instruction is four bytes long, 68k instructions can be as little as two bytes but up to as many as ten.  A single 68k instruction can load a value from a 32 bit memory address specified by one instruction operand and store it at another 32 bit memory address specified by the second instruction operand.  The 68k can also perform other operations beyond simple loads and stores directly on memory.  Or at least appear to...  In truth, computer memory only sends and receives data - no other data processing (like adding, subtracting &amp;amp; etc) occurs in memory.  While the 68k instruction '''add.l&amp;amp;nbsp;#$12345678,(a0)''' appears to add the immediate value of it's first operand to whatever may already be stored at the address pointed to by a0, the contents of that address are actually loaded from memory into a private work register, the addition is performed and then the result is stored back to the same memory location.  So this instruction actually performs two memory accesses where it might appear that there was only one.  Contrast this with PPC assembly programming where memory loads and stores are all done explicitly.  Before data can be operated upon it must be loaded from memory into a GPR (General Purpose Register), zero (in the case of a simple memory copy) or more operations can then be performed and then the data may be stored back to memory.  &lt;br /&gt;
&lt;br /&gt;
Unless you are brand-spanking-new to the topic of PPC assembly, you will already know that the PPC has 32 GPRs - r0 through r31.  But did you know that the desired use of these registers is set out in something called the System V.4 ABI which MorphOS adheres to?  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	r0 - volatile&lt;br /&gt;
	r1 - stack pointer&lt;br /&gt;
	r2 - for system use (with MorphOS, r2 points to the EmulHandle structure)&lt;br /&gt;
&lt;br /&gt;
	r3 - initialised with a pointer to a Dos command buffer&lt;br /&gt;
	r4 - initialised with the length of the Dos command buffer&lt;br /&gt;
	r5 - initialised with a pointer to an ELF structure&lt;br /&gt;
&lt;br /&gt;
	r3 ... r10 volatile &amp;amp; can be used to pass function arguments.  If more &lt;br /&gt;
		arguments are required, the stack is used.  &lt;br /&gt;
&lt;br /&gt;
	r11 &amp;amp; r12 - volatile&lt;br /&gt;
&lt;br /&gt;
	r13 - small data area pointer.  If this register is needed by a function or &lt;br /&gt;
		subroutine, it must be saved first and then restored before &lt;br /&gt;
		returning to where it was called from.  &lt;br /&gt;
&lt;br /&gt;
	r14 ... r31 - No predefined purpose.  If these registers are needed by a &lt;br /&gt;
		function or subroutine, they must be saved first and then restored &lt;br /&gt;
		before returning to where it was called from.  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above use of the word 'volatile' means that functions are not expected to preserve the contents of these registers.  r1 &amp;amp; r2 are the only registers that must be restored to their initial values by a terminating program, however, while most programs will modify r1 and later restore it, it is best to have not modified r2 in the first place.  &lt;br /&gt;
&lt;br /&gt;
This System V.4 ABI also sets out a particular way for programs and subroutines to organise their stack frames.  When a program is loaded into memory and the instruction execution sequence passes to it, the stack pointer is still pointing to the calling program's stack frame and there is also an important address stored in the Link Register at this time.  Unless this program is very simple (like shorty) it must save the Link Register address and, most likely, create it's own stack frame.  Somewhat conveniently, there is a special position in the caller's stack frame that a callee program can save the contents of the Link Register to.  This is a fairly common example of a program or subroutine's very first instructions.&lt;br /&gt;
&lt;br /&gt;
[[File:Awkward-program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Uh indeed...  Let's try to visualise some memory being used as stack space.  &lt;br /&gt;
&lt;br /&gt;
[[File:Stack-diagram16.png]]&lt;br /&gt;
&lt;br /&gt;
Note that '''stwu&amp;amp;nbsp;r1,-8(r1)''' creates a two-word stack frame which is the smallest stack that a program or subroutine can have if it, in turn, calls another program, subroutine or library function.  More often, a larger stack frame is created although, '''stwu&amp;amp;nbsp;r1,-4(r1)''' could be used by a program or subroutine to create a one-word stack frame but this would be redundant and such a program must not call any other program, subroutine or library function.  Such a program would not need to store the value in the Link Register (LR) to prevent it from being overwritten by subsequent calls and can terminate and return to it's caller with a simple '''blr''' instruction - just like shorty does.  &lt;br /&gt;
&lt;br /&gt;
A further note about larger stack frames and appropriate stack sizes: For reasons relating to PPC architecture, it is a good idea to choose stack frame sizes that are multiples of 16 bytes.  &lt;br /&gt;
&lt;br /&gt;
This is a less common example of a program's first instructions but it may better illustrate how to use stack frames.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-initialisation.png]]&lt;br /&gt;
&lt;br /&gt;
Let's jump ahead and look at the last few instructions involved in program termination that would 'undo' the above instructions.  &lt;br /&gt;
&lt;br /&gt;
[[File:Program-termination.png]]&lt;br /&gt;
&lt;br /&gt;
==A Little Less Talk And A Little More Action Please==&lt;br /&gt;
&lt;br /&gt;
It's time to compile another program - this one will actually do something.  &lt;br /&gt;
&lt;br /&gt;
But wait...  &lt;br /&gt;
&lt;br /&gt;
Not another 'Hello World' program...  I'm afraid so.  This time, copy and paste is probably quicker.  ''A fully commented version will be made available for download soon.''&lt;br /&gt;
&lt;br /&gt;
Note that this example does not use the MorphOS SDK.  Instead, some 'quick and dirty' methods are used for the sake of simplicity and readability.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Various library function offsets		&lt;br /&gt;
.set	_LVOOpenLibrary,-552	&lt;br /&gt;
.set	_LVOCloseLibrary,-414	&lt;br /&gt;
.set	_LVOVPrintf,-954	&lt;br /&gt;
.set	_AbsExecBase,4	&lt;br /&gt;
		&lt;br /&gt;
# EmulHandle structure (always pointed to by r2)		&lt;br /&gt;
.set	reg_d0,0	&lt;br /&gt;
.set	reg_d1,4	&lt;br /&gt;
.set	reg_d2,8	&lt;br /&gt;
.set	reg_d3,12	&lt;br /&gt;
.set	reg_d4,16	&lt;br /&gt;
.set	reg_d5,20	&lt;br /&gt;
.set	reg_d6,24	&lt;br /&gt;
.set	reg_d7,28	&lt;br /&gt;
.set	reg_a0,32	&lt;br /&gt;
.set	reg_a1,36	&lt;br /&gt;
.set	reg_a2,40	&lt;br /&gt;
.set	reg_a3,44	&lt;br /&gt;
.set	reg_a4,48	&lt;br /&gt;
.set	reg_a5,52	&lt;br /&gt;
.set	reg_a6,56	&lt;br /&gt;
.set	reg_a7,60	&lt;br /&gt;
.set	EmulCallDirectOS,100	&lt;br /&gt;
		&lt;br /&gt;
# Stack frame offsets		&lt;br /&gt;
.set	stack_pos0_caller_stack,0	&lt;br /&gt;
.set	stack_pos1_callerLR,4	&lt;br /&gt;
.set	stack_pos2_ExecBase,8	&lt;br /&gt;
.set	stack_pos3_DosBase,12	&lt;br /&gt;
.set	new_4_word_stack,16	&lt;br /&gt;
		&lt;br /&gt;
.text		&lt;br /&gt;
		&lt;br /&gt;
	mflr	r0&lt;br /&gt;
	stw	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	stwu	r1,-new_4_word_stack(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r3,dosName@ha&lt;br /&gt;
	addi	r3,r3,dosName@l&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	li	r3,0&lt;br /&gt;
	stw	r3,reg_d0(r2)&lt;br /&gt;
	li	r3,_AbsExecBase&lt;br /&gt;
	lwz	r3,0(r3)&lt;br /&gt;
	stw	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOOpenLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	cmpwi	r3,0&lt;br /&gt;
	beq	exit&lt;br /&gt;
		&lt;br /&gt;
	stw	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
		&lt;br /&gt;
	lis	r4,string1@ha&lt;br /&gt;
	addi	r4,r4,string1@l&lt;br /&gt;
	stw	r4,reg_d1(r2)&lt;br /&gt;
	li	r4,0&lt;br /&gt;
	stw	r4,reg_d2(r2)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOVPrintf&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	lwz	r3,stack_pos3_DosBase(r1)&lt;br /&gt;
	stw	r3,reg_a1(r2)&lt;br /&gt;
	lwz	r3,stack_pos2_ExecBase(r1)&lt;br /&gt;
	stw	r3,reg_a6(r2)&lt;br /&gt;
	li	r3,_LVOCloseLibrary&lt;br /&gt;
	lwz	r0,EmulCallDirectOS(r2)&lt;br /&gt;
	mtctr	r0&lt;br /&gt;
	bctrl	&lt;br /&gt;
		&lt;br /&gt;
	li	r3,0&lt;br /&gt;
		&lt;br /&gt;
exit:	addi	r1,r1,new_4_word_stack&lt;br /&gt;
	lwz	r0,stack_pos1_callerLR(r1)&lt;br /&gt;
	mtlr	r0&lt;br /&gt;
	blr	&lt;br /&gt;
		&lt;br /&gt;
.rodata		&lt;br /&gt;
		&lt;br /&gt;
__abox__:		&lt;br /&gt;
		&lt;br /&gt;
dosName:		&lt;br /&gt;
.string	dos.library	&lt;br /&gt;
		&lt;br /&gt;
string1:		&lt;br /&gt;
.string &amp;quot;Hello World\n&amp;quot;		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this source file as HelloWorld.p and open a shell window.  Change directory to where HelloWorld.p was just saved and enter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vasmppc_std -Felf -o ram:hw.o HelloWorld.p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, because of the simplicity of this program, linking isn't necessary so just enter the following in the shell window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ram:hw.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you impressed?  Feel free to modify, experiment with and improve this source code.  A not-too-difficult challenge might be to change this program so that it prints the arguments given to it in the shell window - a number of small but significant changes would be needed to do this.  &lt;br /&gt;
&lt;br /&gt;
When choosing which registers to use in your own programs, be aware that use of r0 in some instruction operands will not always work as you might expect.  In these instructions, the actual content of r0 is ignored and the result is based on the constant value zero instead.  For example, imagine that r0 contains the value 100 and then this instruction is executed: '''addi&amp;amp;nbsp;r0,r0,50''' It looks like the result should be r0&amp;amp;nbsp;=&amp;amp;nbsp;r0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;150  The result will actually be r0&amp;amp;nbsp;=&amp;amp;nbsp;0&amp;amp;nbsp;+&amp;amp;nbsp;50&amp;amp;nbsp;=&amp;amp;nbsp;50  This may seem odd but, as long as the programmer is aware of it, it can be useful.  A good PPC instruction reference manual will explain this, and many other things, in much greater detail.  There are many of these reference documents available on the internet - this is one of them [http://www.freescale.com/files/product/doc/MPCFPE32B.pdf MPCFPE32B.pdf]&lt;br /&gt;
&lt;br /&gt;
==MorphOS SDK, Objdump, ELFs &amp;amp; Sections==&lt;br /&gt;
&lt;br /&gt;
In addition to installing vbcc, it is also recommended to install the [http://www.morphos-team.net/files/sdk-20100617.lha MorphOS SDK] and the [http://mail.pb-owl.de/~frank/vbcc/current/vbcc_target_ppc-morphos.lha vbcc MorphOS compiler target]. &lt;br /&gt;
&lt;br /&gt;
The installer script of the latter seems to expect that there is a pre-existing assign for include: and, if your system already assigns include: to somewhere, please skip over this next part.  &lt;br /&gt;
&lt;br /&gt;
What follows is my S:user-startup after the installation of vbcc, it's MorphOS compiler target and an additional assign that I made preceded by this comment - &lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;&lt;br /&gt;
; MorphOS user-startup&lt;br /&gt;
;&lt;br /&gt;
; This script is executed on system boot by&lt;br /&gt;
; startup-sequence. You can make personal&lt;br /&gt;
; changes in here.&lt;br /&gt;
;&lt;br /&gt;
; $VER: user-startup 1.1&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
; Enable the following to mount the inet-handler. Note that TCP: allows&lt;br /&gt;
; easy access to internet, and allows scripts to listen for incoming&lt;br /&gt;
; connections. Some malware could abuse this.&lt;br /&gt;
;Mount TCP:&lt;br /&gt;
;BEGIN vbcc&lt;br /&gt;
assign &amp;gt;NIL: vbcc: mos26:vbcc&lt;br /&gt;
assign &amp;gt;NIL: C: vbcc:bin ADD&lt;br /&gt;
setenv VBCC vbcc:&lt;br /&gt;
;END vbcc&lt;br /&gt;
&lt;br /&gt;
;vbcc MorphOS target needs include: to be assigned to somewhere&lt;br /&gt;
assign include: vbcc:targets/ppc-morphos/include&lt;br /&gt;
&lt;br /&gt;
;BEGIN vbcc-ppc-morphos&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: vbcc:targets/ppc-morphos/include&lt;br /&gt;
assign &amp;gt;NIL: vincludemos: include: add&lt;br /&gt;
assign &amp;gt;NIL: vlibmos: vbcc:targets/ppc-morphos/lib&lt;br /&gt;
;END vbcc-ppc-morphos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned just before the previous source code example, some quick and dirty methods were used for the sake of simplicity and readability and this refers to the way library function offsets were established.  This approach will quickly become detrimental as more offsets are added.  There are a number of solutions to this problem but only one will be presented here and it involves the removal of the leading underscore character from function names and appending '@l' to the end so that, for example, '''li&amp;amp;nbsp;r3,_LVOOpenLibrary''' becomes '''li&amp;amp;nbsp;r3,LVOOpenLibrary@l'''.  Assemble with vasm as before but note that the resulting object file is no longer executable.  To make this object executable, vlink is needed.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -o &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above shell command, -lamiga refers to the libamiga.a file that vlink knows to look for in vlibmos:  This file contains information used to resolve many library function names to numerical values.  Note that any executable generated from the above vlink command will contain a lot of symbol information that, while potentially useful, increases the size of the executable.  This can be avoided with a few additions to the above command.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vlink -b elf32morphos -s -x -P__abox__ &amp;lt;desired executable name&amp;gt; &amp;lt;existing object name&amp;gt; -lamiga&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-s strip symbols from the output file&amp;lt;br&amp;gt;&lt;br /&gt;
-x discard local symbols from input file(s)&amp;lt;br&amp;gt;&lt;br /&gt;
-P&amp;lt;symbol&amp;gt; preserve this symbol&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, please refer to the documentation for vlink and other programs installed with vbcc.  &lt;br /&gt;
&lt;br /&gt;
At this point it would be useful to have a number of freshly generated object files and executables to look at with objdump although any ELF can be used for this purpose.  &lt;br /&gt;
&lt;br /&gt;
''final part yet to come''&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Program-termination.png&amp;diff=879</id>
		<title>File:Program-termination.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Program-termination.png&amp;diff=879"/>
				<updated>2010-11-24T13:58:39Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: diagram of commented PPC instructions for program termination&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram of commented PPC instructions for program termination&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Program-initialisation.png&amp;diff=878</id>
		<title>File:Program-initialisation.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Program-initialisation.png&amp;diff=878"/>
				<updated>2010-11-24T13:57:13Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: diagram of commented PPC instructions for early program initialisation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram of commented PPC instructions for early program initialisation&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Stack-diagram16.png&amp;diff=877</id>
		<title>File:Stack-diagram16.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Stack-diagram16.png&amp;diff=877"/>
				<updated>2010-11-24T13:54:36Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: diagram of commented stack entries&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram of commented stack entries&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Awkward-program-initialisation.png&amp;diff=876</id>
		<title>File:Awkward-program-initialisation.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Awkward-program-initialisation.png&amp;diff=876"/>
				<updated>2010-11-24T13:52:19Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: diagram showing three, commented PPC instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram showing three, commented PPC instructions&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Old-and-new.png&amp;diff=875</id>
		<title>File:Old-and-new.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Old-and-new.png&amp;diff=875"/>
				<updated>2010-11-24T13:28:53Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: diagram showing commented 68k and PPC instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;diagram showing commented 68k and PPC instructions&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Main_Page&amp;diff=874</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Main_Page&amp;diff=874"/>
				<updated>2010-11-24T13:07:19Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: /* Development */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;siteLogo&amp;quot; style=&amp;quot;float: right;&amp;quot;&amp;gt; &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:162%; border:none; margin:0; padding:.1em; color:#274572;&amp;quot;&amp;gt;Welcome to the MorphOS Library,&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;top:+0.2em; font-size:95%;&amp;quot;&amp;gt;the wiki based library of MorphOS related documentation.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;articlecount&amp;quot; style=&amp;quot;width:100%; text-align:left; font-size:85%;&amp;quot;&amp;gt;[[Special:Statistics|{{NUMBEROFARTICLES}}]] articles in [[English language|English]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Do you have suggestions or would like to contribute? Please contact: &amp;lt;div id=&amp;quot;message2library&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Important notes to editors:''' [[Basic Guidelines]] - [[List of Wanted Articles]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==MorphOS - The Lightning OS==&lt;br /&gt;
&lt;br /&gt;
* [[What is MorphOS?]]&lt;br /&gt;
* [[Hardware Platforms]]&lt;br /&gt;
* [[Installation]]&lt;br /&gt;
* [[Characteristic features]]&lt;br /&gt;
* [[MorphOS integration]]&lt;br /&gt;
* [[MorphOS Development]]&lt;br /&gt;
* [[Developer tools]]&lt;br /&gt;
* [[3D graphics]]&lt;br /&gt;
* [[Games]]&lt;br /&gt;
* [[MorphOS key applications]]&lt;br /&gt;
* [[Platform expansion]]&lt;br /&gt;
* [[Who needs MorphOS?]]&lt;br /&gt;
* [[Conclusions]]&lt;br /&gt;
* [[Useful links]]&lt;br /&gt;
* [[F.A.Q.]]&lt;br /&gt;
* [[Historical notes]]&lt;br /&gt;
* [[Contributors]]&lt;br /&gt;
&lt;br /&gt;
==Articles==&lt;br /&gt;
The core of the MorphOS Library can be found here.  Along with the provided manuals, there are several documents designed to help users get the most out of their MorphOS powered computer.&lt;br /&gt;
&lt;br /&gt;
* [[Fundamentals of MorphOS]]&lt;br /&gt;
* [[Dictionary of Terms]]&lt;br /&gt;
* [[Shell Commands|Shell: Commands]]&lt;br /&gt;
* [[Pattern matching|Shell: Pattern Matching]]&lt;br /&gt;
* [[Volume Names]]&lt;br /&gt;
&lt;br /&gt;
==Tutorials==&lt;br /&gt;
Welcome to the Tutorials section of the MorphOS Library.  In this aisle of the library you can find examples and step by step instructions to help get the most out of your MorphOS experience.&lt;br /&gt;
&lt;br /&gt;
*[[Modifying the User-Startup file]]&lt;br /&gt;
*[[Dual-boot MorphOS and MacOS X on a Mac Mini G4]]&lt;br /&gt;
*[[How to write Mails with SimpleMail]]&lt;br /&gt;
*[[MorphOS External USB Drive Backup Guide]]&lt;br /&gt;
*[[Scanning with SCANdal]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
In the development section of the MorphOS Library, you can find a collection of helpful articles and tutorials focused on MorphOS software development.&lt;br /&gt;
&lt;br /&gt;
*[[First steps in MorphOS programming]]&lt;br /&gt;
*[[Magic User Interface Programming]]&lt;br /&gt;
*[[In-depth: The New MorphOS Memory System]]&lt;br /&gt;
*[[Reggae: MorphOS multimedia framework]]&lt;br /&gt;
*[[An Introduction to MorphOS PPC Assembly]]&lt;br /&gt;
&lt;br /&gt;
==Benchmarks, Reports &amp;amp; Reviews==&lt;br /&gt;
*[[jPV's MorphOS 2 Review]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
The MorphOS Link Database is a collection of websites that are of interest to all current and potential future users of MorphOS. For easier navigation, we have separated the list of websites into multiple categories.&lt;br /&gt;
&lt;br /&gt;
*[[Links#Community_Portals_.26_Forums|Community Portals]]&lt;br /&gt;
*[[Links#File_Repositories|File Repositories]]&lt;br /&gt;
*[[Links#Software|Software]]&lt;br /&gt;
*[[Links#Developers|Developers]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Work in Progress==&lt;br /&gt;
*[[ReTooled]]&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Ruler1000px.gif&amp;diff=873</id>
		<title>File:Ruler1000px.gif</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Ruler1000px.gif&amp;diff=873"/>
				<updated>2010-11-24T07:58:51Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Used to test width limit for images in library articles.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Used to test width limit for images in library articles.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=%22Hello_world!%22_in_MUI&amp;diff=871</id>
		<title>&quot;Hello world!&quot; in MUI</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=%22Hello_world!%22_in_MUI&amp;diff=871"/>
				<updated>2010-11-19T05:28:08Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: minor readability fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:helloworld.png|left]] This is the window of the example MUI application. It is very simple, it contains only one static text object and no gadgets, except for window border gadgets. Note that the number of gadgets on the right side of the window depends on user MUI settings. The source code of the application is very simple too and fits into 60 lines, including proper vertical spacing. It is cut in pieces in the article for better reading. A complete, ready to compile version [http://krashan.ppa.pl/morphzone_tutorials/helloworld_mui.c is available] too.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;proto/muimaster.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Header files for ''muimaster.library'' and ''intuition.library'' are included. Note that these libraries will be [[MorphOS_API_and_Its_Organization#How_to_Use_a_Library_in_an_Application|opened and closed automatically]].&lt;br /&gt;
 &lt;br /&gt;
 Object *App, *Win;&lt;br /&gt;
&lt;br /&gt;
Global pointers for the application object and the window object. While using many global variables is considered inelegant, having globals for the most important objects is handy, especially in such a small project.&lt;br /&gt;
 &lt;br /&gt;
 Object* build_gui(void)&lt;br /&gt;
 {&lt;br /&gt;
   App = MUI_NewObject(MUIC_Application,&lt;br /&gt;
     MUIA_Application_Author, (ULONG)&amp;quot;Grzegorz Kraszewski&amp;quot;,&lt;br /&gt;
     MUIA_Application_Base, (ULONG)&amp;quot;HELLOWORLD&amp;quot;,&lt;br /&gt;
     MUIA_Application_Copyright, (ULONG)&amp;quot;© 2010 Grzegorz Kraszewski&amp;quot;,&lt;br /&gt;
     MUIA_Application_Description, (ULONG)&amp;quot;Hello World in MUI.&amp;quot;,&lt;br /&gt;
     MUIA_Application_Title, (ULONG)&amp;quot;Hello World&amp;quot;,&lt;br /&gt;
     MUIA_Application_Version, (ULONG)&amp;quot;$VER: HelloWorld 1.0 (16.11.2010)&amp;quot;,&lt;br /&gt;
     MUIA_Application_Window, (ULONG)(Win = MUI_NewObject(MUIC_Window,&lt;br /&gt;
       MUIA_Window_Title, (ULONG)&amp;quot;Hello World&amp;quot;,&lt;br /&gt;
       MUIA_Window_RootObject, MUI_NewObject(MUIC_Group,&lt;br /&gt;
         MUIA_Group_Child, MUI_NewObject(MUIC_Text,&lt;br /&gt;
           MUIA_Text_Contents, (ULONG)&amp;quot;Hello world!&amp;quot;,&lt;br /&gt;
         TAG_END),&lt;br /&gt;
       TAG_END),&lt;br /&gt;
     TAG_END)),&lt;br /&gt;
   TAG_END);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
The above function creates the complete object tree for ''HelloWorld''. The master object is the ''Application'' class instance. It has a ''Window'' object. The window root is a ''Group'' object containing one ''Text'' object. The application object has 6 attributes working as descriptors used in different places in the system. They are not required for running the program, but help integrating it with the system. The meaning of these attributes is explained in the autodoc of ''Application'' class in the SDK. The rest of the attributes are self-explaining, please refer to the autodocs of respective MUI classes for details.&lt;br /&gt;
&lt;br /&gt;
The function illustrates a typical way of creating a MUI interface. The complete object tree is created in one big ''MUI_NewObject()'' call containing nested sub-calls. The order of code execution is different to the order of reading. The most nested objects are created first and passed to constructors of their parents. The application object is created last. This way of creating the application also ensures automatic error handling. If any of constructors fails, it passes ''NULL'' to a parent constructor, making it fail too and then dispose all successfully constructed child objects. Finally the application constructor fails and returns ''NULL''. Then only two states of the application are possible: either the application is fully constructed, or it is not constructed at all. This behaviour greatly simplifies error handling.&lt;br /&gt;
&lt;br /&gt;
 void notifications(void)&lt;br /&gt;
 {&lt;br /&gt;
   DoMethod(Win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2,&lt;br /&gt;
    MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next step is to make notifications. This simple program contains only one notification, which terminates the program after the window close gadget is clicked. MUI maps a left mouse button click on the gadget to a change of ''MUIA_Window_CloseRequest'' attribute. The notification target is the application, the ''MUIM_Application_ReturnID()'' method then passes the quit action identifier to the main loop.&lt;br /&gt;
&lt;br /&gt;
 void main_loop(void)&lt;br /&gt;
 {&lt;br /&gt;
   ULONG signals = 0;&lt;br /&gt;
 &lt;br /&gt;
   set(Win, MUIA_Window_Open, TRUE);&lt;br /&gt;
 			 &lt;br /&gt;
   while (DoMethod(App, MUIM_Application_NewInput, &amp;amp;signals) != MUIV_Application_ReturnID_Quit)&lt;br /&gt;
   {&lt;br /&gt;
     signals = Wait(signals | SIGBREAKF_CTRL_C);&lt;br /&gt;
     if (signals &amp;amp; SIGBREAKF_CTRL_C) break;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   set(Win, MUIA_Window_Open, FALSE);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The standard main loop has been discussed in the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|previous chapter]]. The only addition is opening the window before the loop and closing it after.&lt;br /&gt;
&lt;br /&gt;
 int main(void)&lt;br /&gt;
 {&lt;br /&gt;
   App = build_gui();&lt;br /&gt;
 &lt;br /&gt;
   if (App)&lt;br /&gt;
   {&lt;br /&gt;
     notifications();&lt;br /&gt;
     main_loop();&lt;br /&gt;
     MUI_DisposeObject(App);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Finally, the main function of the program. It builds the object tree first and checks if it succeeded. In case of a fail, the program ends immediately. After all the objects are created, notifications are added and the program enters the main loop. When the loop finishes, the application object is disposed. It also disposes all its sub-objects.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Event_Driven_Programming,_Notifications&amp;diff=870</id>
		<title>Event Driven Programming, Notifications</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Event_Driven_Programming,_Notifications&amp;diff=870"/>
				<updated>2010-11-19T02:35:27Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: minor readability fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Event Driven Programming==&lt;br /&gt;
&lt;br /&gt;
Event driven programming is the natural consequence of the invention and development of graphical user interfaces. Most traditional, command line programs work like a pipe: data are loaded, processed and saved. There is no, or limited user interaction (like adjusting processing parameters, or choosing an alternative path). A GUI changes all that. A GUI based program initializes itself, opens a window with some icons and gadgets, then '''waits''' for user actions. Fragments of the program are executed in response to user input, after an action is finished, the program goes back to waiting. This way the program flow is determined not by the code, but rather by input events sent to the program by the user via the operating system. This is the basic paradigm of event driven programming.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:mzone_eventdriven_1.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''Fig. 1. Execution flow of an event driven program.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notifications in MUI==&lt;br /&gt;
&lt;br /&gt;
There are two approaches to input event decoding in an event driven program: centralized and decentralized. Centralized decoding is programmed as a big conditional statement (a ''switch'' statement usually, or a long cascade of ''if'' statements) inside the main loop of the fig. 1. flowchart. Depending on the decoded event, subroutines performing requested actions are called. Decentralized input event decoding is a more modern idea. In this case, the GUI toolkit receives and handles incoming input events internally and maps them to attribute changes of GUI objects (for example, clicking with the mouse on a button changes its attribute to &amp;quot;pressed&amp;quot;). Then an application programmer can assign actions to attribute changes of chosen objects. This is done by creating '''notifications''' on objects.&lt;br /&gt;
&lt;br /&gt;
MUI uses decentralized input event decoding. All input events are mapped to attribute changes of different objects. These are visible GUI gadgets (controls) usually, but some events may be mapped to attributes of a window object, or an application object (the last one has no visible representation). After creating the complete object tree, but before entering the main loop, the program sets up notifications, assigning actions to attribute changes. Notifications can also be created and deleted dynamically at any time.&lt;br /&gt;
&lt;br /&gt;
A notification connects two objects together. The source object triggers the action after one of its attributes changes. The assigned action (method) is then performed on the target object. The notification is set up by calling the ''MUIM_Notify()'' method on the source object. Arguments of the method can be divided into the source part and the target part. The general form of the ''MUIM_Notify()'' call is shown below:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(source, '''MUIM_Notify''', attribute, value, target, param_count, action, /* parameters */);&lt;br /&gt;
&lt;br /&gt;
The first four arguments form the '''source''' part, the rest is the '''target''' part. The complete call can be &amp;quot;translated&amp;quot; to a human language in the following way:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;center&amp;gt;When the '''source''' object changes its '''attribute''' to the '''value''',&amp;lt;br&amp;gt;perform '''action''' method on the '''target''' object with '''parameters'''.&amp;lt;/center&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is one argument not explained with the above sentence, namely ''param_count''. This is just the number of parameters following this argument. The minimum number of parameters is 1 (the action method identifier), there is no upper limit other than using common sense.&lt;br /&gt;
&lt;br /&gt;
A notification is triggered when an attribute is set to a specified value. It is often useful to have a notification on '''any''' attribute change. A special value ''MUIV_EveryTime'' should be used as a triggering value in this case.&lt;br /&gt;
&lt;br /&gt;
The target action of a notification can be any method. There are a few methods designed specifically to be used in notifications:&lt;br /&gt;
&lt;br /&gt;
'''''MUIM_Set()''''' is another method for setting an attribute. It is used when a notification has to set an attribute on the target object. ''OM_SET()'' is not suitable for using in notifications because it takes a [[Taglists|taglist]] containing attributes to be set. This taglist cannot be built from arguments and must be defined separately. ''MUIM_Set()'' sets a single attribute to a specified value. They are passed to the method directly as two separate arguments. The example below opens a window when a button is pressed:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE, window, 3, MUIM_Set, MUIA_Window_Open, TRUE);&lt;br /&gt;
&lt;br /&gt;
Those not familiar with MUI may ask why the triggering value is set as ''FALSE''. It is related to the default behaviour of button gadgets. The gadget triggers when the left mouse button is '''released''', so at the end of a click. The ''MUIA_Pressed'' attribute is set to ''TRUE'' when the mouse button is pushed down, and set to ''FALSE'' when the mouse button is released. Now it should be obvious why the notification is set to trigger at a ''MUIA_Pressed'' change to ''FALSE''.&lt;br /&gt;
&lt;br /&gt;
'''''MUIM_NoNotifySet()''''' works the same as ''MUIM_Set()'' with one important exception. It does not trigger any notifications set on the target object when the attribute has changed. It is often used to avoid notification loops, not only in notification, but also standalone in the code.&lt;br /&gt;
&lt;br /&gt;
'''''MUIM_MultiSet()''''' allows for setting the same attribute to the same value for multiple objects. Objects are specified as this method's arguments and the final argument should be ''NULL''. Here is an example, disabling three buttons after a checkmark is deselected:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(checkmark, MUIM_Notify, MUIA_Selected, FALSE, application, 7, MUIM_MultiSet,&lt;br /&gt;
  MUIA_Disabled, TRUE, button1, button2, button3, NULL);&lt;br /&gt;
&lt;br /&gt;
What is interesting is that while the target notification object is completely irrelevant here, it must still be a valid object pointer. The application object is usually used for this purpose, or the notification source object. &lt;br /&gt;
&lt;br /&gt;
'''''MUIM_CallHook()''''' calls an external callback function called a [[hook]]. It is often abused by programmers being reluctant to perform subclassing of standard classes, instead implementing program functionality as new methods. Calling a method from a notification is usually faster and easier (however, a hook needs some additional structures to be defined). &lt;br /&gt;
&lt;br /&gt;
'''''MUIM_Application_ReturnID()''''' returns a 32-bit integer number to [[#The_Ideal_MUI_Main_Loop|the main loop]] of a MUI program. With this method MUI's decentralized handling of input events can be turned into a centralized one. MUI programming beginners tend to abuse this method and redirect all the event handling back to the main loop, putting a big ''switch'' statement there. While rather simple, this programming technique should be avoided in favour of implementing program functionality in methods. Adding code inside the main loop degrades the GUI responsiveness. The only legitimate use of ''MUIM_Application_ReturnID()'' is to return a special value ''MUIV_Application_ReturnID_Quit'' used for ending the program.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reusing Triggering Value==&lt;br /&gt;
&lt;br /&gt;
When the action of a notification is to set an attribute in the target object, it is often desired to forward the triggering value to the target object. It is very easy, when the notification is set to occur on a particular value. Things change however, when the notification is set to occur on any value with ''MUIV_EveryTime''. A special value ''MUIV_TriggerValue'' may be used for this. It is replaced with the actual value of the triggering attribute at every trigger. Another special value, ''MUIV_NotTriggerValue'' is used for boolean attributes and is replaced by a logical negation of the current value of the triggering attribute.&lt;br /&gt;
&lt;br /&gt;
The first example uses ''MUIV_Trigger_Value'', to display the value of a slider in a string gadget:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(slider, MUIM_Notify, MUIA_Numeric_Value, MUIV_EveryTime, string, 3,&lt;br /&gt;
  MUIM_Set, MUIA_String_Integer, '''MUIV_TriggerValue''');&lt;br /&gt;
&lt;br /&gt;
The second example connects a checkmark with a button. When the checkmark is selected, the button is enabled. Deselecting the checkmark disables the button:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(checkmark, MUIM_Notify, MUIA_Selected, MUIV_EveryTime, button, 3,&lt;br /&gt;
  MUIM_Set, MUIA_Disabled, '''MUIV_NotTriggerValue''');&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;''MUIV_EveryTime'', ''MUIV_TriggerValue'' and ''MUIV_NotTriggerValue'' are defined as particular values in the 32-bit range. Because of this, it is impossible to set a notification on the value 1 233 727 793 (which is ''MUIV_EveryTime''). It is also impossible to set the value to a fixed number 1 233 727 793 (''MUIV_TriggerValue'') or 1 233 727 795 (''MUIV_NotTriggerValue'') using ''MUIM_Set()'' in a notification.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notification Loops==&lt;br /&gt;
&lt;br /&gt;
There may be hundreds of notifications defined in a complex program. Changing an attribute may trigger a notification cascade. It is possible that the cascade contains loops. The simplest example of a notification loop is a pair of objects having notifications on each other. Let's assume there are two sliders which should be coupled together. It means moving one slider should move the other one as well. A set of two notifications can ensure this behaviour.&lt;br /&gt;
&lt;br /&gt;
 DoMethod(slider1, MUIM_Notify, MUIA_Numeric_Value, MUIV_EveryTime, slider2, 3,&lt;br /&gt;
  MUIM_Set, MUIA_Numeric_Value, MUIV_Trigger_Value); &lt;br /&gt;
 DoMethod(slider2, MUIM_Notify, MUIA_Numeric_Value, MUIV_EveryTime, slider1, 3,&lt;br /&gt;
  MUIM_Set, MUIA_Numeric_Value, MUIV_Trigger_Value); &lt;br /&gt;
&lt;br /&gt;
When the user moves ''slider1'' to value 13, the first notification triggers and sets ''slider2'' value to 13. This triggers the second notification. Its action is to set ''slider1'' value to 13, which in turn triggers the first notification again. Then the loop triggers itself endlessly... Or rather it would, if MUI had no anti-looping measures. The solution is very simple: '''if an attribute is set for an object to the same value as the current one, any notifications on this attribute in this object are ignored'''. In our example the loop will be broken after the second notification sets the value of ''slider1''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The Ideal MUI Main Loop==&lt;br /&gt;
&lt;br /&gt;
The ideal main loop of a MUI program should contain almost no code inside. All actions should be handled with notifications. Here is the code of the loop:&lt;br /&gt;
&lt;br /&gt;
 ULONG signals = 0;&lt;br /&gt;
 &lt;br /&gt;
 while (DoMethod(application, MUIM_Application_NewInput, (ULONG)&amp;amp;signals)&lt;br /&gt;
  != (ULONG)MUIV_Application_ReturnID_Quit)&lt;br /&gt;
 {&lt;br /&gt;
   signals = Wait(signals | SIGBREAKF_CTRL_C);&lt;br /&gt;
   if (signals &amp;amp; SIGBREAKF_CTRL_C) break;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The variable ''signals'' contains a bit-mask of input event signals sent to the process by the operating system. Its initial value 0 just means &amp;quot;no signals&amp;quot;. When the ''MUIM_Application_NewInput()'' method is performed on the application object, MUI sets signal bits for input events it expects in the ''signals'' variable. These signals are usually signals of application windows' message ports, where ''Intuition'' sends input events. Then the application calls the ''exec.library'' function ''Wait()''. Inside this function, the execution of the process is stopped. The process scheduler will not give any processor time to the process until one of the signals in the mask arrives. Other than input event signals set by MUI, only the system CTRL-C signal is added to the mask. Every well written MorphOS application should be breakable by sending this signal. It can be sent via the console by pressing the CTRL + C keys, or from tools like the TaskManager. When one of the signals in the mask arrives at the process, the program returns from ''Wait()''. If the CTRL-C signal is detected, the main loop ends. If not, MUI decodes the received input events based on its received signal mask, translates events to changes of attributes of relevant objects and performs the triggered notifications. All this happens inside the ''MUIM_Application_NewInput()'' method. Finally the signal mask is updated. If any notification calls the ''MUIM_Application_ReturnID()'' method, the identifier passed is returned as the result of ''MUIM_Application_NewInput()''. In the event of receiving the special value ''MUIV_Application_ReturnID_Quit'' the loop ends.&lt;br /&gt;
&lt;br /&gt;
Any additional code inserted into the loop will introduce delay in GUI handling and redrawing. If a program does some processor intensive calculations, the best way to deal with them is to delegate them into a subprocess. Loading the main process with computational tasks may result in the program being perceived as slow and unresponsive to user actions.&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Short_BOOPSI_Overview&amp;diff=869</id>
		<title>Short BOOPSI Overview</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Short_BOOPSI_Overview&amp;diff=869"/>
				<updated>2010-11-19T01:22:23Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: minor readability fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
==Object Oriented Programming==&lt;br /&gt;
&lt;br /&gt;
Object oriented programming is a technique developed as a response to two trends in the computer market. The first one was increasing complexity of software. Management of a traditionally written codebase becomes harder when the code size increases. The second trend was the increasing popularity of graphical user interfaces, which meant the end of sequential execution of programs. Instead modern programs are '''event driven''', which means the flow of code execution is determined by external events (like user input) and is not known at the time of writing the program. Object oriented programming divides a program into a set of objects interacting with each other using well defined interfaces. Such a modularization simplifies the management of a software project and also fits naturally with the concept of modern graphical user interfaces. User controls (called &amp;quot;gadgets&amp;quot; in MUI) are just objects in the code and they interact with other objects representing user data.&lt;br /&gt;
&lt;br /&gt;
This short introduction is not intended to be a complete lecture on object oriented programming. On the other hand no knowledge of any particular object oriented programming language is required to get familiar with BOOPSI.  Usually the support for OOP techniques comes with a programming language, which is either designed for OOP (like C++, C# or Java) or has OOP support added in a more or less logical way (Objective C, PHP). This is not the case for BOOPSI and MUI however. In this case object oriented programming support comes from the operating system. BOOPSI and MUI can be used with any programming language, including traditional ones, for example C and even assembler.&lt;br /&gt;
&lt;br /&gt;
The BOOPSI module is located in the ''intuition.library'', with some important functions being added from a statically linked ''libabox''. Its primary design goal was to build a framework for wrapping Intuition GUI elements in an object oriented interface. This approach was unfortunately not flexible enough, so MUI uses only the basic BOOPSI framework. This framework provides the four basic concepts of object oriented programming: '''classes''', '''objects''', '''methods''' and '''attributes'''. It also supports class inheritance. Because of its simplicity, BOOPSI is easy to understand and use, especially when compared to more sophisticated frameworks, like the one in the C++ programming language.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Classes==&lt;br /&gt;
&lt;br /&gt;
A class is the basic term of object oriented programming. It is the complete description of its objects, their attributes and methods. In the BOOPSI framework, a class consists of:&lt;br /&gt;
*An ''IClass'' structure. A pointer to this structure is used as a reference to the class. The ''IClass'' structure is defined in the ''&amp;lt;intuition/classes.h&amp;gt;'' system header file. There is also the ''Class'' type, which is the same as ''struct IClass''.&lt;br /&gt;
* A class dispatcher function. When an application calls a method on an object, the object's class dispatcher is called. The dispatcher checks the method's identifier and jumps to this method code. The dispatcher is usually implemented as a big ''switch'' statement. For simple classes, which implement only a few short methods, code of these methods is often placed inside ''case'' statements. Bigger classes have methods' code separated into functions placed outside of the dispatcher. As every method goes through a dispatcher, all BOOPSI methods are virtual in the C++ meaning. For this reason, calling a method in BOOPSI is usually slower than in C++.&lt;br /&gt;
&lt;br /&gt;
A class defines a set of methods available for its objects (instances) by the set of ''case'' statements in the dispatcher. Object's attributes are set using the ''OM_SET()'' method and are gotten using ''OM_GET()''. The attributes may also be passed to the object constructor directly. The set of attributes for a class and applicability of the attributes are then defined by the source code of ''OM_NEW()'' (the constructor), ''OM_SET()'' and ''OM_GET()'' methods. There is no formal declaration of class. There is also no division between public and private methods and attributes. Some kind of formal declaration and levels of access may be imposed by putting every class in a separate source code file. An accompanying header file would contain definitions of method identifiers, attribute identifiers and method parameters structures, but only those considered &amp;quot;public&amp;quot;. Private method identifiers should be defined inside the source code of the class, so they are not visible outside of the class source code.&lt;br /&gt;
&lt;br /&gt;
A BOOPSI class can be shared between applications. All the MUI built-in classes are shared ones. The BOOPSI maintains a system-wide list of public classes (the list can be browsed with the ''Scout'' monitoring tool). Shared classes are identified by names. A part of the MUI standard classes is contained inside the main MUI library &amp;amp;ndash; ''muimaster.library''. The library adds these classes to the system list when opened for the first time. The rest of the MUI standard classes are stored on the system disk partition in the ''MOSSYS:Classes/MUI/'' directory. Additional third party classes may be placed in the ''SYS:Classes/MUI'' directory.&lt;br /&gt;
&lt;br /&gt;
Shared classes use the MorphOS shared library framework, in other words a shared BOOPSI class is just a kind of shared library. The class adds itself to the public list of classes, when it is opened from disk. As such, a BOOPSI shared class should be opened with ''OpenLibrary()'' before use ([[MorphOS_API_and_Its_Organization#Manual_Library_Opening_and_Closing|see details]]), especially as BOOPSI classes are usually not included into the list of libraries opened automatically. '''This is not the case for MUI classes''' however. MUI shared classes can be used without opening them. It is explained below, in the [[Short_BOOPSI_Overview#MUI_Extensions_to_BOOPSI|MUI Extensions to BOOPSI]] section.&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
&lt;br /&gt;
====Methods====&lt;br /&gt;
Methods are just actions, which can be performed on an object. A set of available methods is defined by the object's class. Technically speaking, a method is a function called with an object as its parameter in order to change the object's state. In BOOPSI, methods are called using the ''DoMethod()'' call from ''libabox'':&lt;br /&gt;
&lt;br /&gt;
 result = DoMethod(object, method_id, ... /* method parameters */);&lt;br /&gt;
 result = DoMethodA(object, method_struct);&lt;br /&gt;
&lt;br /&gt;
The first, more popular form of the call just builds the method structure on the fly, from arguments passed to it. Any method structure always has the method identifier as the first field. The ''DoMethodA()'' call gets a pointer to the method structure, the structure is built by the application. The second form is rarely used. The number and meaning of parameters, as well as the meaning of the result are method specific. Comparison of executing a method with both forms of the call is given below:&lt;br /&gt;
&lt;br /&gt;
 struct MUIP_SomeMethod&lt;br /&gt;
 {&lt;br /&gt;
   ULONG MethodID;&lt;br /&gt;
   LONG ParameterA;&lt;br /&gt;
   LONG ParameterB;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, MUIM_SomeMethod, 3, 7);&lt;br /&gt;
 &lt;br /&gt;
 struct MUIP_SomeMethod mparams = { MUIM_SomeMethod, 3, 7 };&lt;br /&gt;
 DoMethodA(object, &amp;amp;mparams);&lt;br /&gt;
&lt;br /&gt;
The ''DoMethod()'' form is more convenient, so it is commonly used. MUI uses specific prefixes for all its structures and constants:&lt;br /&gt;
* '''''MUIM_''''' for method identifiers.&lt;br /&gt;
* '''''MUIP_''''' for method parameter structures.&lt;br /&gt;
* '''''MUIA_''''' for attribute identifiers.&lt;br /&gt;
* '''''MUIV_''''' for special, predefined attribute values.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;The C types used in the method structure above may need some explanation. LONG is a 32-bit signed integer, ULONG is an unsigned one. Because the structure is usually built on the processor stack, all parameters are extended and aligned to 32 bits. Then every parameter in the structure must be defined either as a 32-bit integer or a pointer. Any parameter larger than 32 bits must be passed via pointer (for example double precision floats or strings).&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Setting an Attribute====&lt;br /&gt;
&lt;br /&gt;
An object's attributes represent its properties. They are written and read using special methods, ''OM_SET()'' and ''OM_GET()'' respectively. This differs from most object oriented programming languages, where attributes (being implemented as an object's fields) are accessed directly. Manipulating attributes in BOOPSI is slower then, as it implies performing a method.&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' method does not take a single attribute and its value, but a [[Taglists|taglist]] of them, so one can set multiple attributes at once. The setting of two attributes to an object may be done as follows:&lt;br /&gt;
&lt;br /&gt;
 struct TagItem attributes[] = {&lt;br /&gt;
   { MUIA_SomeAttr1, 756 },&lt;br /&gt;
   { MUIA_SomeAttr2, 926 },&lt;br /&gt;
   { TAG_END, 0 }&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, OM_SET, (ULONG)attributes);&lt;br /&gt;
&lt;br /&gt;
However, this is cumbersome and the code is not easily readable. The ''intuition.library'' makes it easier by providing the ''SetAttrsA()'' function, which is a wrapper for the ''OM_SET()'' method. Using this function and the array defined above, one can write:&lt;br /&gt;
&lt;br /&gt;
 SetAttrsA(object, attributes);&lt;br /&gt;
&lt;br /&gt;
It still requires definition of a temporary [[Taglists|taglist]], but the function also has a variadic (meaning it can take a variable number of arguments) form ''SetAttrs()'', which allows for building the taglist on-the-fly:&lt;br /&gt;
&lt;br /&gt;
 SetAttrs(object,&lt;br /&gt;
   MUIA_SomeAttr1, 756,&lt;br /&gt;
   MUIA_SomeAttr2, 926,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
This is not all however. Programmers are lazy and decided that in the common case of setting a single attribute, ''SetAttrs()'' is still too much typing. A common practice found in sources using MUI was to define an ''xset()'' or ''set()'' macro, which is now defined in the system headers, in the ''&amp;lt;libraries/mui.h&amp;gt;'' file.&lt;br /&gt;
&lt;br /&gt;
 #define set(object, attribute, value) SetAttrs(object, attribute, value, TAG_END)&lt;br /&gt;
&lt;br /&gt;
Then, setting a single attribute can be coded as follows:&lt;br /&gt;
&lt;br /&gt;
 set(object, MUIA_SomeAttr1, 756);&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' method returns the number of attributes applied to the object. If some attributes are not known to the object's class (and superclasses), they are not counted. This return value is usually ignored, it may be used for testing an attribute applicability.&lt;br /&gt;
&lt;br /&gt;
MUI provides a few additional methods for setting attributes, namely ''MUIM_Set()'', ''MUIM_NoNotifySet()'' and ''MUIM_MultiSet()''. They are mainly used in [[Event_Driven_Programming,_Notifications#Notifications_in_MUI|notifications]].&lt;br /&gt;
&lt;br /&gt;
====Getting an Attribute====&lt;br /&gt;
&lt;br /&gt;
The ''OM_GET()'' method gets a single attribute from an object. There is no multiple attributes getting method. Its first, obvious parameter is the attribute identifier. The attribute value is not returned as the result of the method however. Instead the second parameter is a pointer to a memory area, where the value is to be stored. This allows for passing attributes larger than 32 bits, they are just copied to the pointed memory area. This only works for fixed size attributes. Text strings cannot be passed this way, so they are passed as pointers (a pointer to the string is stored at a place in memory pointed to by the second parameter of ''OM_GET()''). The three examples below demonstrate all three cases:&lt;br /&gt;
&lt;br /&gt;
 LONG value1;&lt;br /&gt;
 QUAD value2;    /* 64-bit signed integer */&lt;br /&gt;
 STRPTR *value3;&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute1, (ULONG)&amp;amp;value1);  /* integer attr */&lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute2, (ULONG)&amp;amp;value2);  /* fixed size big attr */&lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute3, (ULONG)&amp;amp;value3);  /* string attr */&lt;br /&gt;
&lt;br /&gt;
In cases when an attribute is returned by pointer, the data pointed to should be treated as read-only unless documented otherwise.&lt;br /&gt;
&lt;br /&gt;
Similarly as for ''OM_SET()'', there is a wrapper function for ''OM_GET()'' in the ''intuition.library'', named ''GetAttr()''. This function unexpectedly changes the order of arguments: attribute identifier is the first, object pointer is the second. The three examples above may be written with ''GetAttr()'' as follows:&lt;br /&gt;
&lt;br /&gt;
 GetAttr(MUIA_Attribute1, object, &amp;amp;value1);&lt;br /&gt;
 GetAttr(MUIA_Attribute2, object, (ULONG*)&amp;amp;value2);&lt;br /&gt;
 GetAttr(MUIA_Attribute3, object, (ULONG*)&amp;amp;value3);&lt;br /&gt;
&lt;br /&gt;
The third parameter, a storage pointer is prototyped as pointer to ULONG, so in the first example type casting is not needed.&lt;br /&gt;
&lt;br /&gt;
The ''&amp;lt;libraries/mui.h&amp;gt;'' system header file defines a macro ''get()'', which reverses the order of the two first arguments of ''GetAttr()'' and adds the typecasting to ''ULONG*''. The order of arguments of ''get()'' is the same as for ''set()'', which helps to avoid mistakes. The third line of the above example may be rewritten with ''get()'' this way:&lt;br /&gt;
&lt;br /&gt;
 get(object, MUIA_Attribute3, &amp;amp;value3);&lt;br /&gt;
&lt;br /&gt;
The most often used attributes are integers (32-bit or shorter) and strings. Both of them fit into a 32-bit variable, as strings have to be passed via pointers. Taking this into account, MUI programmers invented a function (sometimes defined as a macro), which just returns the attribute value instead of storing it at a specified address. The function is named ''xget()'' and works as shown below:&lt;br /&gt;
&lt;br /&gt;
 value1 = xget(object, MUIA_Attribute1);&lt;br /&gt;
 /* MUIA_Attribute2 can't be retrieved with xget() */&lt;br /&gt;
 value3 = (STRPTR)xget(object, MUIA_Attribute3);&lt;br /&gt;
&lt;br /&gt;
The ''xget()'' function may be defined in the following way:&lt;br /&gt;
&lt;br /&gt;
 inline ULONG xget(Object *obj, ULONG attribute)&lt;br /&gt;
 {&lt;br /&gt;
   ULONG value;&lt;br /&gt;
 &lt;br /&gt;
   GetAttr(attribute, object, &amp;amp;value);&lt;br /&gt;
   return value;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function is very simple and is compiled to a few processor instructions. That is why it is declared as ''inline'', which causes the compiler to insert the function's code in-place instead of generating a jump. This makes the code faster, albeit a bit bigger. Except for working only with 32-bit attributes, ''xget()'' also has the disadvantage of loosing the ''OM_GET()'' return value. The value is boolean and is ''TRUE'' if the object's class (or any of its superclasses) recognizes the attribute, ''FALSE'' otherwise. This value is usually ignored, but may be useful for scanning objects for supported attributes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;The ''xget()'' function is not defined in the system headers. It has been described here because of its common use in MUI applications. Its counterparts for bigger sized arguments may be defined if needed.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Object Construction==&lt;br /&gt;
&lt;br /&gt;
Having a class, the programmer can create an unlimited number of objects (instances) of this class. Every object has its own instance data area, which is allocated and cleared automatically by the BOOPSI. Of course only object data are allocated for each instance. The code is not duplicated, so it must be reentrant (static variables and code self-modification must not be used).&lt;br /&gt;
&lt;br /&gt;
Objects are created and disposed with two special methods: the constructor, ''OM_NEW()'' and the destructor, ''OM_DISPOSE()''. Of course the constructor method cannot be called on an object, because it creates a new one. It needs a pointer to the object's class instead, so it cannot be invoked with ''DoMethod()''. The ''intuition.library'' provides ''NewObjectA()'' and ''NewObject()'' functions for calling the constructor. The difference between them is that ''NewObjectA()'' takes a pointer to a [[Taglists|taglist]] specifying initial values for objects. ''NewObject()'' allows the programmer to build this taglist from a variable number of function arguments.&lt;br /&gt;
&lt;br /&gt;
''NewObject[A]()'' has two alternative ways of specifying the created object's class. Private classes are specified by pointers of ''Class'' type. Shared classes are specified by name, which is a null-terminated string. If the pointer is used for class specification, the name should be NULL, if a name is used, the pointer should be ''NULL''. Four examples below show creating instances of private and public class with both ''NewObjectA()'' and ''NewObject()'':&lt;br /&gt;
&lt;br /&gt;
 Object *obj;&lt;br /&gt;
 Class *private;&lt;br /&gt;
 &lt;br /&gt;
 struct TagItem initial = {&lt;br /&gt;
   { MUIA_Attribute1, 4 },&lt;br /&gt;
   { MUIA_Attribute2, 46 },&lt;br /&gt;
   { TAG_END, 0 }&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
A private class, NewObjectA():&lt;br /&gt;
&lt;br /&gt;
 obj = NewObjectA(private, NULL, initial);&lt;br /&gt;
&lt;br /&gt;
A private class, NewObject():&lt;br /&gt;
&lt;br /&gt;
 obj = NewObject(private, NULL,&lt;br /&gt;
   MUIA_Attribute1, 4,&lt;br /&gt;
   MUIA_Attribute2, 46,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
A public class, NewObjectA():&lt;br /&gt;
&lt;br /&gt;
 obj = NewObjectA(NULL, &amp;quot;some.class&amp;quot;, initial);&lt;br /&gt;
&lt;br /&gt;
A public class, NewObject():&lt;br /&gt;
&lt;br /&gt;
 obj = NewObject(NULL, &amp;quot;some.class&amp;quot;,&lt;br /&gt;
   MUIA_Attribute1, 4,&lt;br /&gt;
   MUIA_Attribute2, 46,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
''NewObject[A]()'' returns ''NULL'' in case of an object creation failure. Usual reasons are: wrong class pointer/name, lack of free memory, wrong/missing initial values of attributes. The return value of ''NewObject[A]()'' should always be checked in the code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Object Destruction==&lt;br /&gt;
&lt;br /&gt;
The ''OM_DISPOSE()'' method is used to destroy an object. Unlike ''OM_NEW()'' the destructor may be invoked with ''DoMethod()'':&lt;br /&gt;
&lt;br /&gt;
 DoMethod(object, OM_DISPOSE);&lt;br /&gt;
&lt;br /&gt;
The ''intuition.library'' has a wrapper for this however, named ''DisposeObject()'':&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(object);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==MUI Extensions to BOOPSI==&lt;br /&gt;
&lt;br /&gt;
The Magic User Interface not only builds on BOOPSI but also extends it. Other than providing a broad set of classes, MUI also modifies the BOOPSI mode of operation a bit. Two modifications are discussed in this chapter: extension of the ''IClass'' structure and MUI's own functions for object construction and destruction.&lt;br /&gt;
&lt;br /&gt;
MUI uses the ''MUI_CustomClass'' structure for its internal class representation. This structure contains the standard ''Class'' structure inside. It is important when creating objects from MUI private classes with ''NewObject()'', that the ''Class'' structure must be extracted from the ''MUI_CustomClass'' structure:&lt;br /&gt;
&lt;br /&gt;
 struct MUI_CustomClass *priv_class;&lt;br /&gt;
 Object *obj;&lt;br /&gt;
 &lt;br /&gt;
 obj = NewObject('''priv_class-&amp;gt;mcc_Class''', NULL, /* ... */ TAG_END);&lt;br /&gt;
&lt;br /&gt;
MUI's second modification of BOOPSI is using its own functions for object construction and destruction, ''MUI_NewObject[A]()'' and ''MUI_DisposeObject()'' respectively. These two functions are used '''only''' for objects of MUI shared (public) classes. Objects of private classes are created with ''NewObject()'' as shown above. The main advantage of ''MUI_NewObject()'' is automatic opening and closing of disk based shared classes. Here is an example:&lt;br /&gt;
&lt;br /&gt;
 Object *text;&lt;br /&gt;
 &lt;br /&gt;
 text = MUI_NewObject(MUIC_Text, MUIA_Text_Contents, &amp;quot;foobar&amp;quot;, TAG_END);&lt;br /&gt;
&lt;br /&gt;
'''MUIC_Text'' is a macro defined in ''&amp;lt;libraries/mui.h&amp;gt;'' and it expands to &amp;quot;Text.mui&amp;quot; string. All MUI public classes should be referenced by their ''MUIC_'' macros rather than by direct string literals. It helps to detect mistyped class names, as a typo in a macro will be detected during compilation. The MUI checks if a class named ''Text.mui'' has been added to the public list of classes. If not, the class is found on disk, opened and used for creating the requested object. Closing the class when no longer in use is handled automatically too. All MUI objects should be disposed using ''MUI_DisposeObject()'', which takes the object to be disposed as its only argument, the same as ''DisposeObject()''.&lt;br /&gt;
&lt;br /&gt;
 MUI_DisposeObject(text);&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Short_BOOPSI_Overview&amp;diff=803</id>
		<title>Short BOOPSI Overview</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Short_BOOPSI_Overview&amp;diff=803"/>
				<updated>2010-11-05T23:33:58Z</updated>
		
		<summary type="html">&lt;p&gt;AusPPC: Spelling and grammar fixes - some of which I introduced...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
==Object Oriented Programming==&lt;br /&gt;
&lt;br /&gt;
Object oriented programming is a technique developed as a response to two trends in the computer market. The first one was increasing complexity of software. Management of a traditionally written codebase becomes harder when the code size increases. The second trend was the increasing popularity of graphical user interfaces, which meant the end of sequential execution of programs. Instead modern programs are '''event driven''', which means the flow of code execution is determined by external events (like user input) and is not known at the time of writing the program. Object oriented programming divides a program into a set of objects interacting with each other using well defined interfaces. Such a modularization simplifies the management of a software project and also fits naturally with the concept of modern graphical user interfaces. User controls (called &amp;quot;gadgets&amp;quot; in MUI) are just objects in the code and they interact with other objects representing user data.&lt;br /&gt;
&lt;br /&gt;
This short introduction is not intended to be a complete lecture on object oriented programming. On the other hand no knowledge of any particular object oriented programming language is required to get familiar with BOOPSI.  Usually the support for OOP techniques comes with a programming language, which is either designed for OOP (like C++, C# or Java) or has OOP support added in a more or less logical way (Objective C, PHP). This is not the case for BOOPSI and MUI however. In this case object oriented programming support comes from the operating system. BOOPSI and MUI can be used with any programming language, including traditional ones, for example C and even assembler.&lt;br /&gt;
&lt;br /&gt;
The BOOPSI module is located in the ''intuition.library'', with some important functions being added from a statically linked ''libabox''. Its primary design goal was to build a framework for wrapping Intuition GUI elements in an object oriented interface. This approach was unfortunately not flexible enough, so MUI uses only the basic BOOPSI framework. This framework provides the four basic concepts of object oriented programming: '''classes''', '''objects''', '''methods''' and '''attributes'''. It also supports class inheritance. Because of its simplicity, BOOPSI is easy to understand and use, especially when compared to more sophisticated frameworks, like the one in the C++ programming language.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Classes and Objects==&lt;br /&gt;
&lt;br /&gt;
====Classes====&lt;br /&gt;
&lt;br /&gt;
A class is the basic term of object oriented programming. It is the complete description of its objects, their attributes and methods. In the BOOPSI framework, a class consists of:&lt;br /&gt;
*An ''IClass'' structure. A pointer to this structure is used as a reference to the class. The ''IClass'' structure is defined in the ''&amp;lt;intuition/classes.h&amp;gt;'' system header file. There is also the ''Class'' type, which is the same as ''struct IClass''.&lt;br /&gt;
* A class dispatcher function. When an application calls a method on an object, the object's class dispatcher is called. The dispatcher checks the method's identifier and jumps to this method code. The dispatcher is usually implemented as a big ''switch'' statement. For simple classes, which implement only a few short methods, code of these methods is often placed inside ''case'' statements. Bigger classes have methods' code separated into functions placed outside of the dispatcher. As every method goes through a dispatcher, all BOOPSI methods are virtual in the C++ meaning. For this reason, calling a method in BOOPSI is usually slower than in C++.&lt;br /&gt;
&lt;br /&gt;
A class defines a set of methods available for its objects (instances) by the set of ''case'' statements in the dispatcher. Object's attributes are set using the ''OM_SET()'' method and are gotten using ''OM_GET()''. The attributes may also be passed to the object constructor directly. The set of attributes for a class and applicability of the attributes are then defined by the source code of ''OM_NEW()'' (the constructor), ''OM_SET()'' and ''OM_GET()'' methods. There is no formal declaration of class. There is also no division between public and private methods and attributes. Some kind of formal declaration and levels of access may be imposed by putting every class in a separate source code file. An accompanying header file would contain definitions of method identifiers, attribute identifiers and method parameters structures, but only those considered &amp;quot;public&amp;quot;. Private method identifiers should be defined inside the source code of the class, so they are not visible outside of the class source code.&lt;br /&gt;
&lt;br /&gt;
A BOOPSI class can be shared between applications. All the MUI built-in classes are shared ones. The BOOPSI maintains a system-wide list of public classes (the list can be browsed with the ''Scout'' monitoring tool). Shared classes are identified by names. A part of the MUI standard classes is contained inside the main MUI library &amp;amp;ndash; ''muimaster.library''. The library adds these classes to the system list when opened for the first time. The rest of the MUI standard classes are stored on the system disk partition in the ''MOSSYS:Classes/MUI/'' directory. Additional third party classes may be placed in the ''SYS:Classes/MUI'' directory.&lt;br /&gt;
&lt;br /&gt;
====Objects====&lt;br /&gt;
&lt;br /&gt;
==Methods and Attributes==&lt;br /&gt;
&lt;br /&gt;
====Methods====&lt;br /&gt;
Methods are just actions, which can be performed on an object. A set of available methods is defined by the object's class. Technically speaking, a method is a function called with an object as its parameter in order to change the object's state. In BOOPSI, methods are called using the ''DoMethod()'' call from ''libabox'':&lt;br /&gt;
&lt;br /&gt;
 result = DoMethod(object, method_id, ... /* method parameters */);&lt;br /&gt;
 result = DoMethodA(object, method_struct);&lt;br /&gt;
&lt;br /&gt;
The first, more popular form of the call just builds the method structure on the fly, from arguments passed to it. Any method structure always has the method identifier as the first field. The ''DoMethodA()'' call gets a pointer to the method structure, the structure is built by the application. The second form is rarely used. The number and meaning of parameters, as well as the meaning of the result are method specific. Comparison of executing a method with both forms of the call is given below:&lt;br /&gt;
&lt;br /&gt;
 struct MUIP_SomeMethod&lt;br /&gt;
 {&lt;br /&gt;
   ULONG MethodID;&lt;br /&gt;
   LONG ParameterA;&lt;br /&gt;
   LONG ParameterB;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, MUIM_SomeMethod, 3, 7);&lt;br /&gt;
 &lt;br /&gt;
 struct MUIP_SomeMethod mparams = { MUIM_SomeMethod, 3, 7 };&lt;br /&gt;
 DoMethodA(object, &amp;amp;mparams);&lt;br /&gt;
&lt;br /&gt;
The ''DoMethod()'' form is more convenient, so it is commonly used. MUI uses specific prefixes for all its structures and constants:&lt;br /&gt;
* '''''MUIM_''''' for method identifiers.&lt;br /&gt;
* '''''MUIP_''''' for method parameter structures.&lt;br /&gt;
* '''''MUIA_''''' for attribute identifiers.&lt;br /&gt;
* '''''MUIV_''''' for special, predefined attribute values.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;The C types used in the method structure above may need some explanation. LONG is a 32-bit signed integer, ULONG is an unsigned one. Because the structure is usually built on the processor stack, all parameters are extended and aligned to 32 bits. Then every parameter in the structure must be defined either as a 32-bit integer or a pointer. Any parameter larger than 32 bits must be passed via pointer (for example double precision floats or strings).&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An object's attributes represent its properties. They are written and read using special methods, ''OM_SET()'' and ''OM_GET()'' respectively. This differs from most object oriented programming languages, where attributes (being implemented as an object's fields) are accessed directly. Manipulating attributes in BOOPSI is slower then, as it implies performing a method.&lt;br /&gt;
&lt;br /&gt;
====Setting an Attribute====&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' method does not take a single attribute and its value, but a [[Taglists|taglist]] of them, so one can set multiple attributes at once. The setting of two attributes to an object may be done as follows:&lt;br /&gt;
&lt;br /&gt;
 struct TagItem attributes[] = {&lt;br /&gt;
   { MUIA_SomeAttr1, 756 },&lt;br /&gt;
   { MUIA_SomeAttr2, 926 },&lt;br /&gt;
   { TAG_END, 0 }&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, OM_SET, (ULONG)attributes);&lt;br /&gt;
&lt;br /&gt;
However, this is cumbersome and the code is not easily readable. The ''intuition.library'' makes it easier by providing the ''SetAttrsA()'' function, which is a wrapper for the ''OM_SET()'' method. Using this function and the array defined above, one can write:&lt;br /&gt;
&lt;br /&gt;
 SetAttrsA(object, attributes);&lt;br /&gt;
&lt;br /&gt;
It still requires definition of a temporary [[Taglists|taglist]], but the function also has a variadic (meaning it can take a variable number of arguments) form ''SetAttrs()'', which allows for building the taglist on-the-fly:&lt;br /&gt;
&lt;br /&gt;
 SetAttrs(object,&lt;br /&gt;
   MUIA_SomeAttr1, 756,&lt;br /&gt;
   MUIA_SomeAttr2, 926,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
This is not all however. Programmers are lazy and decided that in the common case of setting a single attribute, ''SetAttrs()'' is still too much typing. A common practice found in sources using MUI was to define an ''xset()'' or ''set()'' macro, which is now defined in the system headers, in the ''&amp;lt;libraries/mui.h&amp;gt;'' file.&lt;br /&gt;
&lt;br /&gt;
 #define set(object, attribute, value) SetAttrs(object, attribute, value, TAG_END)&lt;br /&gt;
&lt;br /&gt;
Then, setting a single attribute can be coded as follows:&lt;br /&gt;
&lt;br /&gt;
 set(object, MUIA_SomeAttr1, 756);&lt;br /&gt;
&lt;br /&gt;
The ''OM_SET()'' method returns the number of attributes applied to the object. If some attributes are not known to the object's class (and superclasses), they are not counted. This return value is usually ignored, it may be used for testing an attribute applicability.&lt;br /&gt;
&lt;br /&gt;
MUI provides a few additional methods for setting attributes, namely ''MUIM_Set()'', ''MUIM_NoNotifySet()'' and ''MUIM_MultiSet()''. They are mainly used in [[notifications]] and are discussed in the [[Notifications|relevant chapter]].&lt;br /&gt;
&lt;br /&gt;
====Getting an Attribute====&lt;br /&gt;
&lt;br /&gt;
The ''OM_GET()'' method gets a single attribute from an object. There is no multiple attributes getting method. Its first, obvious parameter is the attribute identifier. The attribute value is not returned as the result of the method however. Instead the second parameter is a pointer to a memory area, where the value is to be stored. This allows for passing attributes larger than 32 bits, they are just copied to the pointed memory area. This only works for fixed size attributes. Text strings cannot be passed this way, so they are passed as pointers (a pointer to the string is stored at a place in memory pointed to by the second parameter of ''OM_GET()''). The three examples below demonstrate all three cases:&lt;br /&gt;
&lt;br /&gt;
 LONG value1;&lt;br /&gt;
 QUAD value 2;    /* 64-bit signed integer */&lt;br /&gt;
 STRPTR *value3;&lt;br /&gt;
 &lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute1, (ULONG)&amp;amp;value1);  /* integer attr */&lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute2, (ULONG)&amp;amp;value2);  /* fixed size big attr */&lt;br /&gt;
 DoMethod(object, OM_GET, MUIA_Attribute3, (ULONG)&amp;amp;value3);  /* string attr */&lt;br /&gt;
&lt;br /&gt;
In cases when an attribute is returned by pointer, the data pointed to should be treated as read-only unless documented otherwise.&lt;br /&gt;
&lt;br /&gt;
Similarly as for ''OM_SET()'', there is a wrapper function for ''OM_GET()'' in the ''intuition.library'', named ''GetAttr()''. This function unexpectedly changes the order of arguments: attribute identifier is the first, object pointer is the second. The three examples above may be written with ''GetAttr()'' as follows:&lt;br /&gt;
&lt;br /&gt;
 GetAttr(MUIA_Attribute1, object, &amp;amp;value1);&lt;br /&gt;
 GetAttr(MUIA_Attribute2, object, (ULONG*)&amp;amp;value2);&lt;br /&gt;
 GetAttr(MUIA_Attribute3, object, (ULONG*)&amp;amp;value3);&lt;br /&gt;
&lt;br /&gt;
The third parameter, a storage pointer is prototyped as pointer to ULONG, so in the first example type casting is not needed.&lt;br /&gt;
&lt;br /&gt;
The ''&amp;lt;libraries/mui.h&amp;gt;'' system header file defines a macro ''get()'', which reverses the order of the two first arguments of ''GetAttr()'' and adds the typecasting to ''ULONG*''. The order of arguments of ''get()'' is the same as for ''set()'', which helps to avoid mistakes. The third line of the above example may be rewritten with ''get()'' this way:&lt;br /&gt;
&lt;br /&gt;
 get(object, MUIA_Attribute3, &amp;amp;value3);&lt;br /&gt;
&lt;br /&gt;
The most often used attributes are integers (32-bit or shorter) and strings. Both of them fit into a 32-bit variable, as strings have to be passed via pointers. Taking this into account, MUI programmers invented a function (sometimes defined as a macro), which just returns the attribute value instead of storing it at a specified address. The function is named ''xget()'' and works as shown below:&lt;br /&gt;
&lt;br /&gt;
 value1 = xget(object, MUIA_Attribute1);&lt;br /&gt;
 /* MUIA_Attribute2 can't be retrieved with xget() */&lt;br /&gt;
 value3 = (STRPTR)xget(object, MUIA_Attribute3);&lt;br /&gt;
&lt;br /&gt;
The ''xget()'' function may be defined in the following way:&lt;br /&gt;
&lt;br /&gt;
 inline ULONG xget(Object *obj, ULONG attribute)&lt;br /&gt;
 {&lt;br /&gt;
   ULONG value;&lt;br /&gt;
 &lt;br /&gt;
   GetAttr(attribute, object, &amp;amp;value);&lt;br /&gt;
   return value;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function is very simple and is compiled to a few processor instructions. That is why it is declared as ''inline'', which causes the compiler to insert the function's code in-place instead of generating a jump. This makes the code faster, albeit a bit bigger. Except for working only with 32-bit attributes, ''xget()'' also has the disadvantage of loosing the ''OM_GET()'' return value. The value is boolean and is ''TRUE'' if the object's class (or any of its superclasses) recognizes the attribute, ''FALSE'' otherwise. This value is usually ignored, but may be useful for scanning objects for supported attributes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;The ''xget()'' function is not defined in the system headers. It has been described here because of its common use in MUI applications. Its counterparts for bigger sized arguments may be defined if needed.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Object Construction and Destruction==&lt;/div&gt;</summary>
		<author><name>AusPPC</name></author>	</entry>

	</feed>