Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mixed Language programming

53 views
Skip to first unread message

MarkLim

unread,
Apr 10, 2012, 1:56:58 AM4/10/12
to
Hi everyone,

Last year I started to learn the basics of i386/x86-64 assembly
language using NASM armed with an online book written by Dr Paul
Carter. It goes without saying a beginner needs to see an output of
the result(s) of their programs. It is not a trivial thing for
beginners to write their I/O routines. Since the day of the original
Apple II, COUT ($FDED) had been used to display output by assembly
language programmers.

Carter's book recommended using the std library c-function "printf". I
wanted to find out if we could come up with something similar using
ORCA/M and ORCA/C under ORCA shell. The programs below are the results
of these experiments. First, I wrote a simple program which every C
programmer knows.


#include <stdio.h>
int main()
{
printf("Hello, world\n");
}

Compiling it gives 2 files, hello.root and hello.a. Then I did an
object dump on hello.root.

DUMPOBJ +D -H hello.root >tmp.txt

If you take a look at the tmp.txt file, you would discover this is the
file that starts up a C program in the ORCA shell environment , call a
function labelled main and finally shutdown. In fact, compiling any C
file using ORCA/C alway produces a .root file. (Reference: page 21
ORCA/C manual.) The second part of the program is how to call a C
function from Assembly Language. Page 55 of the manual says it is very
simple; only a code snippet to help us out.

Using these ideas, I wrote 2 programs. The main program just add two
numbers and call a C function called foo to display the results.

#include <stdio.h>

int foo (long num1, long num2, long *sum)
{
printf("%ld + %ld = %ld\n", num1, num2, *sum);
}



mcopy main.macs
OBJCASE ON

main start

clc
lda num1
adc num2
sta sum
lda num1+2
adc num2+2
sta sum+2

pushlong #sum
pushlong num2
pushlong num1
jsl foo
rtl

num1 dc i4'2'
num2 dc i4'3'
sum ds 4
end

You can link the object files by typing:

link foo main keep=test

Next to find out if ORCA/C behaves like any C compiler by passing
parameters to the function main. This will be useful later if we want
our assembly language program to get parameters issued at the ORCA
shell command line.

#include <stdio.h>


int foo (int argc, char *argv[])
{
int i;

for (i = 0; i < argc; i++)
printf("%d %s\n", i, argv[i]);
}


mcopy main.macs
OBJCASE ON

main start
ret_val EQU 1

csub (2:argc,4:argv),2
pushlong argv
pushword argc
jsl foo
stz ret_val

ret 2:ret_val

end


Finally, why not call printf directly rather than calling a function
foo to do it?
// dummy
int foo (void)
{
}

mcopy main.macs
OBJCASE ON

main start
ret_val EQU 1
i EQU ret_val+2

csub (2:argc,4:argv),4

stz sum
lda #1 ;for (i=1; i <= 10; i++)
sta i

forloop ANOP
lda i
cmp #10
beq for1
bcs endfor
for1 clc
adc sum ;sum += i;
sta sum
inc i ;i++
bra forloop

endfor ANOP
pushword sum
pushlong #sumstr
pushlong #formatstr
jsl printf
stz ret_val

ret 2:ret_val

sum ds 2


sumstr dc c'sum = '
dc i1'0'
formatstr dc c'%s %d'
dc i1'13'
dc i1'0'

end

We use a dummy foo function to generate the required .root file.

Want to write a sort function in assembly but don't know how. Yes, you
can by "cheating". There are many C sort functions floating on the
Internet. Port one of them to ORCA/C. Make sure it is working properly
(as part of an ORCA/C program).

Then move the sort function to a separate source file by cutting and
pasting; compile it and use DUMPOBJ + output redirection to get a TXT
file. Edit this file by removing unwanted material and adding in
labels. Your original C function will be helpful as you peruse through
the assembly code.

Mark

MarkLim

unread,
Apr 11, 2012, 10:07:52 PM4/11/12
to
Hi,

I have some comments or queries which I hope someone out there may be
able to answer. A search through the old postings of this newsgroup
has given me a better understanding of stack frames. I suppose if the
calling function and called function are in different memory banks,
the programmer will have to save the data bank register (DBR), set it
the called function's program bank & on exit restore the DBR. The ORCA
macros sub & csub don't do this.

ORCA/Modula2 has a different method of setting up a stack frame
compared to ORCA/Pascal or ORCA/C. Calling a C or Pascal function from
Modula2 is documented but what about the reverse i.e. calling a
Modula2 procedure from a C/Pascal function.

Also ORCA/Modula2 does not have macros to handle the calling of
assembly language routines.

Finally, does anyone know how the APWC compiler sets up the entry and
exit code of a function? A stack diagram might be helpful.

Thanks.

Mark

MarkLim

unread,
Apr 18, 2012, 11:27:01 PM4/18/12
to
Apple had developed and distributed a set of macros for the setting up
of stack frames. They are in a file named "M16.Util2". Over the past 1
week, I did a number of tests using those macros with a number of
compilers released for the IIGS (both native and cross platforms).
They work great. There is no need for ORCA's csub, csubroutine macros
etc.

BTW, in earlier (APW) versions, there is a bug in the BegParms
macro; the global arithmetic symbolic parameter BegParmsPC was not
declared.
If you use APWC with the ORCA 2.0x shell, it's better to use LinkIIGS
instead of the ORCA Linker.


Setting up the stack frame is easy once you understand how the macros
work. However, there is no exit code. This is an advantage because
the programmer has the flexibility to implement one based on whatever
stuff he chooses to remove/remain on the stack. The disadvantage is a
program crash if the stack is "corrupted" on return to the calling
function.

As a last experiment, I installed the EMBE/Modula2 compiler on the
HD. After a fair amount of effort, I managed to get a main module
call an assembly language routine. The DefineStack macros were used to
setup the entry code. On first try, it didn't crash. In fact, much
of the time was spent getting familiar with the operations of the
compiler.
The accompanying manual has an accurate stack diagram. Unlike the
other compilers, the passed parameters are just below the top of the
stack. You can just pop them off with a PLx (where x=A,X,Y)
instruction & store them somewhere.

There are several different stack diagrams I came across during these
series of experiments. Some of them are given below; please note it's
only necessary to know what is already on the stack when control is
passed to the assembly language routine.

APW/MPW CIIGS compiler:

| | $100
|-----------------|
| ... |
| parameters | psize
| ... |
|-----------------|
| RTL |
|-----------------|
| old DP |
|-----------------|
| |
| 6 resvd bytes |
| |
|-----------------|
| ... |
| local vars | lsize
| ... |
|-----------------|
SP -> | ... |
| unused bytes |
| ... |
|-----------------|
DP ->| |

Function results are returned in A-reg or (X,A) regs
The last byte of the passed parameters is at $100 with respect to the
new DP reg. There are 6 bytes reserved for internal use.

PascalIIgs compiler:

|-----------------|
| function result |
|-----------------|
| ... |
| parameters | psize
| ... |
|-----------------|
| RTL |
|-----------------|
| old DP |
|-----------------|
| |
| 4 resvd bytes |
| |
|-----------------|
| ... |
| local vars | lsize
| ... |
|-----------------|
SP ->| |<- DP

Function results are returned on the stack.

ORCA/C or ORCA/Pascal compilers:

| |
|-----------------|
| ... |
| parameters | psize
| ... |
|-----------------|
| |
| RTL |
| |
|-----------------|
| ... |
| local vars | lsize
| ... |
|-----------------|
| 2-n reserved |
| bytes |
|-----------------|
| DP |<- DP
| Reg |
|-----------------|
SP -> | |


Function results are returned in A-reg or (X,A) regs. The number of
reserved bytes can vary and is a multiple of 2.

ORCA/Modula2 compiler stack frame:

| |
|-----------------|
| result |
|-----------------|
| ... |
| parameters | psize
| ... |
|-----------------|
| RTL |
|-----------------|
| Old M2Lib SP |
|-----------------|
| Old M2Lib Disp |
|-----------------|
| DPR |
|-----------------|
| ... |
| local vars | lsize
| ... | $16
|-----------------|
| |
| 22 resvd bytes |
| | <- DP
|-----------------|
SP -> | |


Function results are returned on stack.

The stack frame diagram for the EMBE/Modula2 is depicted in the
manual which accompanies the software.

0 new messages