User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Mixing C and assembly?

Sun Mar 17, 2019 7:29 pm

I found a tutorial http://www.science.smith.edu/dftwiki/in ... spberry_Pi that does this, but are the rules written down anywhere? What registers you put things into before you call a routine (like printf) and how the returns might work. I was surprised it looks so easy, I don't know why. I used to mix both Turbo C and Turbo Pascal with 80x86 assembly. There are some serious advantages: you don't need to reinvent the wheel by writing a printf, you just call printf. You could take an existing program and optimize loops by rewriting them in assembly. Crashes are expected while learning, that's OK. Yes, I know you can look at the assembly code coming out of GCC.

jahboater
Posts: 4595
Joined: Wed Feb 04, 2015 6:38 pm

Re: Mixing C and assembly?

Sun Mar 17, 2019 9:23 pm

For interest, the alternative is placing inline assembly code within the C.

The syntax is a bit hard to learn, but the result is very fast because it fully takes part in the optimization of the surrounding code. If you write separate functions in assembler then they will not be optimized.

Nowadays I find C is usually faster than my assembler, so I just tend to use the odd instruction here or there, usually in an "inline" function or macro.

Here is a trivial example:

#define clear_fpe() asm( "msr fpsr,xzr" : )

This replaces the math library function call "feclearexcept( FE_ALL_EXCEPT )" with a single instruction.
(It quickly clears the sticky floating point exception flags).

RattusRattus
Posts: 44
Joined: Sat Sep 29, 2018 11:27 am

Re: Mixing C and assembly?

Sun Mar 17, 2019 9:48 pm

Hi ab1jx

So there are absolute rules for mixing assembly and C. Just traps to catch you out....

The calling convention is very much target specific. At the moment that would be "ARMv6 + Hard Floating point" if you want to work on all Pis. of cause if you just want to go 64 bit for a Pi 3 then you could target "ARMv8 + Hard Floating Point". But of cause what you target needs to be compatible with the rest of the OS on *your* platform...

Portability: If at some point you decide to run your code on a Pi with a different ABI (ok at the moment all Pis share the same ARMv6 HF ABI so this my never be a problem) or even on another ARM platform (a beagle bone black for example) then you will need to change you assembly to match the ABI of that platform. if you want to run on a completely different platform (i.e. AMD64) then not only do you need to learn a new ABI you need to learn a new assembly language as well....
If you keep to just C then changing ABI or even Processor Architecture entirely then the compiler will take care of this for you...

Performance
Actually I would doubt that well written C will perform much worse than well written assembly - certainly you are in diminishing returns territory here but then knowing HOW to interact with the ABI (either in C or Assembly) is still knowladge worth having..

take a look at the following docs:
https://wiki.debian.org/ArmHardFloatPort/VfpComparison
http://infocenter.arm.com/help/topic/co ... libabi.pdf

jahboater
Posts: 4595
Joined: Wed Feb 04, 2015 6:38 pm

Re: Mixing C and assembly?

Sun Mar 17, 2019 9:52 pm

ab1jx wrote:
Sun Mar 17, 2019 7:29 pm
Yes, I know you can look at the assembly code coming out of GCC.
A hint if you want to do that by the way, its much easier if you can use a GCC version 7 or later (the current version is 8.3). With a recent version of GCC you get the C source lines interspersed with the emitted assembler, and it is ten times easier to find things and understand it.

gcc -Os -S -fverbose-asm hello.c -o hello.s
ab1jx wrote:
Sun Mar 17, 2019 7:29 pm
You could take an existing program and optimize loops by rewriting them in assembly.
I used to do that! But nowadays I would say it is futile. The compiler knows all the tricks!

Again, if you use a recent version of GCC, you will very likely not find a single thing you can improve on.
If you do find anything strange the compiler is doing, look around at all the surrounding code, even many many lines away, and you may well then understand why the compiler had to do something.

User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Mixing C and assembly?

Sun Mar 17, 2019 10:35 pm

OK, look at
Extended Asm - Assembler Instructions with C Expression Operands
The asm statement allows you to include assembly instructions directly within C code.
In a GCC PDF or online. But that doesn't answer my question.

Here's a printf example: http://www.science.smith.edu/dftwiki/in ... s_by_Value

Code: Select all

@  sum3.s
@  D. Thiebaut
@  Illustrates how to pass 2 ints by value
@  to a function that adds them up and returns	
@  the sum in r0.

@ ---------------------------------------
@	Data Section
@ ---------------------------------------
	
	.data
	.balign 4	
string: .asciz "\n%d + %d = %d\n"
a:	.word	33
b:	.word	44
c:	.word 	0		@ will contain a+b 
	
@ ---------------------------------------
@	Code Section
@ ---------------------------------------
	
.text
.global main
.extern printf

	
@ ---------------------------------------
@ sumFunc: gets 2 ints in r1 and r2, adds
@ 	them up and saves the results in
@	r0.	
sumFunc:
	push	{ip, lr}
	add	r0, r1, r2
	pop	{ip, pc}

@ ---------------------------------------
@ main: passes 2 ints to sumFunc and prints
@ the resulting value using printf	
main:   push 	{ip, lr}	@ push return address + dummy register
				@ for alignment
	ldr	r1, =a		@ get address of a into r1
	ldr	r1, [r1]	@ get a into r1
	ldr	r2, =b		@ get address of b into r2
	ldr	r2, [r2]	@ get b into r2

	bl	sumFunc		@ pass (r1, r2) to sumFunc
				@ gets sum back in r0
	ldr	r2, =c		@ get address of c into r2
	str	r0, [r2]	@ store r0 into c
	

	@ printf( "%d + %d = %d\n", r1, r2, r3 )
	@ (format-string address passed in r0)
        ldr 	r0, =string 	@ get address of string into r0
	ldr	r1, =a		@ r1 <- a
	ldr	r1, [r1]
	ldr	r2, =b		@ r2 <- b
	ldr	r2, [r2]
	ldr	r3, =c		@ r3 <- c
	ldr	r3, [r3]	@ 
        bl 	printf		@ print string and pass params
				@ into r1, r2, and r3

@ return to OS	
        pop 	{ip, pc}	@ pop return address into pc
 
You assemble and link like

Code: Select all

as -o sum3.o sum3.s
gcc -o sum3 sum3.o
But how do you know to use r0, r1, r2, r3? Is there something that talks about that sort of stuff? I'm interested in framebuffer graphics done in assembly. I think I can open /dev/fb1 and mmap it from C then access the pointer from assembly. I'm calculating 2,073,600 pixels (well, maybe not all of them). If you can access printf from assembly as an extern I should be able to have an assembly file which I run through as to make an object file, which treats the framebuffer pointer in the C as an extern. Then compile the object files together with gcc using a makefile.

jahboater
Posts: 4595
Joined: Wed Feb 04, 2015 6:38 pm

Re: Mixing C and assembly?

Sun Mar 17, 2019 10:51 pm

ab1jx wrote:
Sun Mar 17, 2019 10:35 pm
But how do you know to use r0, r1, r2, r3? Is there something that talks about that sort of stuff?
Its the ABI (application binary interface). It looks like the previous post by @rattusrattus linked to the spec.
Probably the arguments go in r0, r1, r2, r3 ... and the function return value goes on r0.

Perhaps practice with some simpler functions (like puts() perhaps), until you are familiar with the process - I would say that printf is a pretty hard function to deal with!

As an alternative, you may execute system calls directly in assembler. So you may be able to print out your stuff just by calling the write system call (see a hello world example below).
For system calls, the arguments go in the registers r0, r1, r2 ... in the same way, and register 7 contains the system call number. Again the return code is in r0. Note the similarity with the library functions - thats so that the stub functions in the C library such as open() write() etc need do very little work.

Code: Select all

.global _start
_start:
    mov   r0,#1
    adr   r1,message
    mov   r2,#12
    mov   r7,#4
    svc   0      // write
    mov   r7,#1
    svc   0      // exit
message:
    .ascii  "Hello world\n"

RattusRattus
Posts: 44
Joined: Sat Sep 29, 2018 11:27 am

Re: Mixing C and assembly?

Sun Mar 17, 2019 11:16 pm

links inside the ARM document apear to be dead

you will certainly need the Procedure call standard
http://infocenter.arm.com/help/topic/co ... _aapcs.pdf

/Rattus

User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Mixing C and assembly?

Mon Mar 18, 2019 1:34 am

OK, thank you all, this is the sort of stuff I was looking for. I wasn't even quite aware of what an ABI was https://en.wikipedia.org/wiki/Applicati ... _interface Relatively recent term, to me.

The last time I tried to do much with assembly language was about 1994, I had just taken a C course and I was trying to get input from a serial mouse to move the cursor around the screen. C was just too slow, so I found what online resources I could (over my 14.4 modem) and spent a summer teaching myself 80x86 assembly language. Which I never really used again, but it's helpful in a way to know. Peter Norton Programmer's Bible, Ralf Brown Interrupt List, whatever else I could find were my tools of the day. It did the trick, in assembly language things seemed to happen instantly. I wrote 200 byte programs to walk the symbols | / - \ along each line of my screen (pre-windows days). What game writers could do with an Apple2 in 6502 assembly (compared to basic) was just amazing.

But portability becomes an issue and a reason not to dive too deeply into it. Trust GCC I guess. I have a Rock64 and a Pocket Beagle aside from 3 Pis and 3 Zeros and 2 laptops, I'm not going to learn assembly for all of them, I turn 65 this summer. But it's infinitely more interesting than TV.

jahboater
Posts: 4595
Joined: Wed Feb 04, 2015 6:38 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 1:46 am

ab1jx wrote:
Mon Mar 18, 2019 1:34 am
But portability becomes an issue and a reason not to dive too deeply into it. Trust GCC I guess. I have a Rock64 and a Pocket Beagle aside from 3 Pis and 3 Zeros and 2 laptops, I'm not going to learn assembly for all of them, I turn 65 this summer. But it's infinitely more interesting than TV.
Personally I would spend the time learning 64-bit ARM assembler (A64).
I believe it is more modern and easier to learn and use.
It is different from the A32 and is more likely to be useful in the future.
It is slightly more like another assemblers around.

Tzarls
Posts: 224
Joined: Tue Feb 26, 2013 6:59 am

Re: Mixing C and assembly?

Mon Mar 18, 2019 2:45 am

A few years ago I got involved in porting some software to the Raspberry Pi, and had to investigate how function arguments and returns work in assembly - learnt a lot about r, s and d registers. The whole discussiones and work progress is documented here:

https://www.gamedev.net/forums/topic/63 ... pberry-pi/

It is quite large but most of it is just dissasemblies that helped us find out how the ABI works. I think you might find it useful even if you don´t know the exact software we were working on. Give it a chance, at least for the first 2 pages.

Hope this helps.

echmain
Posts: 224
Joined: Fri Mar 04, 2016 8:26 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 3:30 am

jahboater wrote:
Mon Mar 18, 2019 1:46 am
ab1jx wrote:
Mon Mar 18, 2019 1:34 am
But portability becomes an issue and a reason not to dive too deeply into it. Trust GCC I guess. I have a Rock64 and a Pocket Beagle aside from 3 Pis and 3 Zeros and 2 laptops, I'm not going to learn assembly for all of them, I turn 65 this summer. But it's infinitely more interesting than TV.
Personally I would spend the time learning 64-bit ARM assembler (A64).
I believe it is more modern and easier to learn and use.
It is different from the A32 and is more likely to be useful in the future.
It is slightly more like another assemblers around.
I’d like to take a crack at 64 bit Arm assembler.

But a 64 bit OS is required.

Have you installed a 64 bit OS? Gentoo or a different one?

jahboater
Posts: 4595
Joined: Wed Feb 04, 2015 6:38 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 8:05 am

echmain wrote:
Mon Mar 18, 2019 3:30 am
I’d like to take a crack at 64 bit Arm assembler.

But a 64 bit OS is required.

Have you installed a 64 bit OS? Gentoo or a different one?
I use Gentoo64 on the Pi.
Works well, is fast, and comes with GCC 8.2 ready installed!

https://github.com/sakaki-/gentoo-on-rpi3-64bit

This brief ARM doct is a quick first read:
https://static.docs.arm.com/100898/0100 ... 8_0100.pdf

This is a handy overview of the ISA, much smaller than the ARMv8 ARM
https://www.element14.com/community/ser ... Manual.pdf

Use "as" and "ld" or "gcc" as usual.

Looking at what the compiler produces is a good way of learning how things are done.
GCC 8.2 has the new feature for assembler listings. It can intermingle the original C source code lines with the assembly, which makes it very easy to find the code generated for a particular C statement.

gcc -Os -S -fverbose-asm hello.c -o hello.s

echmain
Posts: 224
Joined: Fri Mar 04, 2016 8:26 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 11:49 am

jahboater wrote:
Mon Mar 18, 2019 8:05 am
echmain wrote:
Mon Mar 18, 2019 3:30 am
I’d like to take a crack at 64 bit Arm assembler.

But a 64 bit OS is required.

Have you installed a 64 bit OS? Gentoo or a different one?
I use Gentoo64 on the Pi.
Works well, is fast, and comes with GCC 8.2 ready installed!

https://github.com/sakaki-/gentoo-on-rpi3-64bit

This brief ARM doct is a quick first read:
https://static.docs.arm.com/100898/0100 ... 8_0100.pdf

This is a handy overview of the ISA, much smaller than the ARMv8 ARM
https://www.element14.com/community/ser ... Manual.pdf

Use "as" and "ld" or "gcc" as usual.

Looking at what the compiler produces is a good way of learning how things are done.
GCC 8.2 has the new feature for assembler listings. It can intermingle the original C source code lines with the assembly, which makes it very easy to find the code generated for a particular C statement.

gcc -Os -S -fverbose-asm hello.c -o hello.s
Thanks for this. Looks like it's time to install Gentoo on a spare Pi.

User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Mixing C and assembly?

Mon Mar 18, 2019 1:44 pm

I was running 64 bit Debian on a Pi a year ago, went back to Raspbian because I wanted the stuff in /opt/vc. I'll see if I can find a link to it.

Heater
Posts: 12960
Joined: Tue Jul 17, 2012 3:02 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 1:52 pm

Do you mean pi64?
https://github.com/bamarni/pi64

I still have it running here. But it has not had an update for a long time. Does not work on the 3B+ I believe.

A certain Crazyhead90 has a fork which should work on 3B+.

It's all it bit to messy for me to bother with anymore.

User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Mixing C and assembly?

Mon Mar 18, 2019 2:11 pm

https://people.debian.org/~stapelberg/r ... IEW.img.xz

Seems to still be there, it's over 1 year old so it needs a lot of updates. But it's Buster, not Stretch. From being at a Debian URL I thought it might be sort of official, but I'm on the Debian ARM mailing list and I could never find the guy (Stapleberg). It might have not had support for the Pi's internal wifi so I had to plug in a USB one. Mostly it worked well. It may have gone on to be called pi64, I don't know.

The parent dir https://people.debian.org/~stapelberg/raspberrypi3/ but 1/2018 was the last version.

echmain
Posts: 224
Joined: Fri Mar 04, 2016 8:26 pm

Re: Mixing C and assembly?

Mon Mar 18, 2019 5:37 pm

This link has a working Debian Buster 64 bit:

https://wiki.debian.org/RaspberryPi3

Last updated Feb 7, 2019.

User avatar
ab1jx
Posts: 867
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Mixing C and assembly?

Mon Mar 18, 2019 6:12 pm

echmain wrote:
Mon Mar 18, 2019 5:37 pm
This link has a working Debian Buster 64 bit:

https://wiki.debian.org/RaspberryPi3

Last updated Feb 7, 2019.
Thanks, I grabbed a copy, maybe I'll go back to using it. I'll bet it's the same thing later in life. 64 bit is slightly slower though and being RAM-challenged at a fixed 1 GB there's no great advantage unless you want to work with AARCH64. Which I can do on my Rock64 with 4 GB of RAM.

RattusRattus
Posts: 44
Joined: Sat Sep 29, 2018 11:27 am

Re: Mixing C and assembly?

Mon Mar 18, 2019 9:00 pm

Well it also used ARMv8 not ARMv6 instructions so you will gain there as well.....

/Rattus

Return to “General programming discussion”