GP2X Programming Using Only The Gnu As Assembler?


asm_freak

Still Fresh
Joined
Aug 21, 2006
Messages
4
Hi,

I really enjoy the ARM CPUs with their powerful language set.

Is it possible to program the GP2X using only and alone GNU 'as'? No linking with ld or pre-processing with gcc.

The same way as it's done using FASM. There, you must provide in your assembler code the structure for the PE-files yourself.

Why I am asking this? Because I don't like not to have maximum control of what binary file I'll get as result using ld and so on. There are some magic startup codes inserted using ld. What do they do? I'd prefer to construct the resulting ELF-(GPE-)file with all its structures on my own.

Just a plain WYSIWYG_in_your_executable-assembly on the GP2X would be cool. Some kind of coding .com-files in old DOS days. ;-)

So, possible or not?

Thanks and cheers
 
Roughly speaking, I don't believe there is an equivalent to the .COM format. ELF format is what you use on the gp2x. Unix had a somewhat simpler format ("a.out") but I don't think it is supported any more.

You could write a utility to take an object module and create an ELF format from it, so you would know every detail about what is done. Basically, this takes your code and data sections and tells the unix loader how to find them, how big they are, and where to put them in virtual memory. Then it also contains the entry point to call.

However, the "ld" program does not necessarily insert any startup codes if you use it properly, and can just be used as a convenient way to generate the proper header data for the ELF file.

There's lots of stuff on the interweb about "ELF format" "ld" that provide details.
 
Sometime ago I made some programs using only nasm and ld
And as I opened the program in gdb, it shows me that it starts processing right on my code

Ld can link and write some header for your program, namely defining the entry point or initial stack but no code is injected at all

So I guess you are allowed of writing your program from scratch in pure assembly, you can even translate a program made in C to assembly and then compile using as and finally link it to have pretty much the same program... this option is way if you want to optimize only the main loop in your C program for example
 
asm_freak posted on Aug 21 2006 at 09:36 AM said:
Hi at

I really enjoy the ARM CPUs with their powerful language set.

Is it possible to program the GP2X using only and alone GNU 'as'? No linking with ld or pre-processing with gcc.

The same way as it's done using FASM. There, you must provide in your assembler code the structure for the PE-files yourself.

Why I am asking this? Because I don't like not to have maximum control of what binary file I'll get as result using ld and so on. There are some magic startup codes inserted using ld. What do they do? I'd prefer to construct the resulting ELF-(GPE-)file with all its structures on my own.

Just a plain WYSIWYG_in_your_executable-assembly on the GP2X would be cool. Some kind of coding .com-files in old DOS days. ;-)

So, possible or not?

Thanks and cheers


asm_freak posted on Aug 21 2006 at 09:36 AM said:
Hi at

I really enjoy the ARM CPUs with their powerful language set.

Is it possible to program the GP2X using only and alone GNU 'as'? No linking with ld or pre-processing with gcc.

The same way as it's done using FASM. There, you must provide in your assembler code the structure for the PE-files yourself.

Why I am asking this? Because I don't like not to have maximum control of what binary file I'll get as result using ld and so on. There are some magic startup codes inserted using ld. What do they do? I'd prefer to construct the resulting ELF-(GPE-)file with all its structures on my own.

Just a plain WYSIWYG_in_your_executable-assembly on the GP2X would be cool. Some kind of coding .com-files in old DOS days. ;-)

So, possible or not?

Thanks and cheers


Absolutely, no problem at all...Well, not using LD means you have to write your own LD. You can keep ld out of your shorts. Or you could re-write it, but that is an all together different project, I would switch to some other assembler and linker first. AS far as assemblers go, gas for arm is ackward, it is what it is a kludge of a compiler written for another platform made to work for arm. Find an old copy of arm sdk or ads or something, maybe tcc if they have an arm port. Or just use ld, its not that painful, you can control it...

http://www.dwelchsoftware.com/arm-20060802a.zip should have some examples. Ideally you do want to replace your bootloader with the modified bootloader that lets you boot a .img file. From there it is pretty easy to build all asm programs.

As an alternative, and I think there are some examples above, you can run whatever you want on the 940, very little difference between the 940 and the 920, make your program use a loader program on the 920 (I can get you one if you dont have one, basically it is a modified version of rlyeh's stuff) Leave the 920 in an infinite loop and it will live in the cache and stay out of the way of the 940.

If you are talking writing linux/sdl apps in all asm. well of course you can do that too, write some test programs in C compile to asm and find out what if any name mangling and library calls you need to make then go all asm from there...

I have been off the gp2x for a couple of weeks now, got an Olimex SAM7S-H64 I have been playing with. GCC was killing me, no matter what I did it wanted to write to registers using strb instead of str, I hated the idea of making the write register function an asm function and having to eat the function call every time. The project was pretty simple had it mostly done in asm already, so I dumped gcc and finished in in asm only. Made life much easier. I enjoy letting the C compiler(s) with full optimizations try to optimize code for me, things like (( a>>2)&3)|((b&3)<<2) Sometimes the C compilers comp up with things I had forgotten about like orr r1,r2,r2, lsl #2. Saved me an operation...Then of course some times (often with gcc) it just digs a hole and takes the long road. The arm compilers, sdk, ads, rvct, are simply incredible, the instructions and instruction sequences generated (C code with full optimizations on) are a work of art.

Anything you can do in C or any other language you can do in ASM by definition. (the corrallary is not true).



p.s. all typos and spelling mistakes are intentional...
 
Last edited by a moderator:
Ok, I've tried something using FASMARM and the FreeBSD ELF manpage. I've done something like the first program in the faboulos "GP2X Demo Development Articles Series" posted by Dzz. Just print "Hello World!". ;-)

Because my GP2X hasn't arriven yet, I cannot say if that works on the real console. Using GDB results in that instructions are correctly placed although I cannot execute any SWI-call as they are not implemented in my host system (win32). And after the SWI-call the 'pc'-register is scrambled up. And gdb is a hell to use BTW. ;-)

Anyway, the resulting (assembled) file size is just 370 bytes. It can be probably smaller as I've read the the real Linux ELF loader doesn't rely on sections. So just defining two segments (one code segment and one data segment) would probably run, too. I've tried that, but unfortunately, with only two segments defined in the ELF-file, neither "objdump" nor "gdb" can use the resulting program (with only two sections) as they say that there are no sections available.

Would really like to know, if the resulting ELF file runs on a real GP2X. Can someone test that for me, please?

Thanks and cheers,
asmfreak

Download here
 
I've been building small elfs by assembling with open2x-gcc, and linking with open2x-ld to avoid libc. I put all my data in the .text segment in my assembly code, and use open2x-objcopy to copy "only" the .text section. That still doesn't work - it copies .bss as well - but I hack the resulting executable as follows to remove .bss, the section names, and the section headers, and make .text writable:

* Cut out everything after the first section (.text) - this includes the section names and the section headers, but hopefully nothing else if you put all your data in .text anyway

* Edit the elf header, stating that there are no section headers, and that there's only one program header now. I zero out the section header offset as well as the number of section headers etc. The program header offset is still ok.

* Make .text writable - the flags in its program header (76 bytes into the file?) are 0x05 0x00 0x00 0x00 by default, for read+execute; change the first byte to 0x07, for read+write+execute

* Cut out the second program header - this is usually from 52+32 = 84 bytes, for a further 32 bytes - it should start with 0x01 0x00 0x00 0x00.

* Subtract 32 bytes from various offsets - the length of the first program header, the execution address specified in the elf header, maybe some others I forgot right now

I do this by hand at the moment, and I may have forgotten something here. The open2x binary tools don't seem to support this level of hacking - although objcopy claims to be able to make .text writable, it doesn't seem to work.

If I'm just testing, the only hack I make is to make .text writable - no point in going to all the trouble of condensing the binary if it's just going to crash!

gdb is very handy when things go wrong. Disassemblies make a lot more sense when you wrote the original code yourself!

Edit: the smallest executable I built using this method was 101 bytes (not sure why it was an odd number, I may have just left an extra byte on by mistake). It was just an empty function - I think it came to 4 arm instructions, written by gcc, setting up a stack frame. I guess that means the actual size of the executable is 84 bytes + your code size.
 
gfoot posted on Aug 22 2006 at 01:55 PM said:
(...)That still doesn't work - it copies .bss as well - but I hack the resulting executable as follows to remove .bss, the section names, and the section headers, and make .text writable:(...)
Hmm, I think that it's much easier to use an own header by using a flat assembler like the one I've mentioned. So, you don't need to hack the ELF-file itself with a hexeditor.

More interesting would be then, how to - by using a flat assembler - include third-party libraries that exists in .o- or .a-form. A binary include of the .text- and .data-sections in form of raw db statements into your code would function well, but you've got to get the correct virtual addresses of the included (exported) functions of the third-party library. For that, I think, it's needed to parse the original third-party .o-(.a-)library for the exported symbols to get the file offsets for the locations of the functions and mark them with labels in your code in order to get 'bl' and 'b' access. For imported data it's much more difficult as you've got to calculate (like 'add r0, pc, addrImpData-$') the right virtual memory addresses for both: your own code and the imported code. Or am I missing here something?
 
Last edited by a moderator:
My comments were just about making tiny elfs. If you're linking with third partiy libraries, they probably need the C runtime anyway, so it's pointless to worry about the elf header overhead in comparison. Just use the stock linker to fix up your references.

Generally to refer to globals you need a pointer in your .text section, near the code referring to the global, which you can load through. The linker should fix these up automatically when it links, so you shouldn't have to worry about it. The easiest way to check this stuff out is using the -S switch to gcc, so you can inspect the code it generates.

Of course if you're interested in writing your own linker then that's fair enough, but I wouldn't require the code to know about it.
 
Thanks for this thread guys, I knew there's a good reason to keep reading these forums! :)

I'm starting to work on a 4k demo so I'll be stealing your ideas shortly.
 
gfoot said:
(...)If you're linking with third partiy libraries, they probably need the C runtime anyway, (...)
Yeah, and that's the cruel thing about using libraries. You must have a correct version of the third party library AND of the C runtime library (and anything else) or nothing works as expected. I even say that staticly linked applications aren't really staticly linked as they still depend on external runtime libraries such as C or GLIB and so on. When they would be completely staticly linked, they would run on an empty filesystem with no libraries (libXXXXX.so) at all. But they would be 200MB big or so because they include everything. ;-)

That's the reason why I hate C/C++. With all its header and library stuff. Need that header. For that library you need other libraries and header files. And so on. Not to forget: "Oh, wrong version."

The only clean way in my eyes is to use just what the OS or the hardware (incl. BIOS) themselves provide. Here that are syscalls (somewhat like the MS Windows API?) and hardware registers. If you really have written great code, put that in source code form, so other people can just copy and paste them into their own source codes. My opinion.

Dzz said:
(...)I'm starting to work on a 4k demo so I'll be stealing your ideas shortly.
I'll look at the file headers when you've done it, I swear. ;-p
 
Last edited by a moderator:
Back
Top