
Manually creating an ELF executable - muoncf
http://www.negrebskoh.net/howto/howto_elf_exec.html
======
kragen
If you liked this, you'll probably like even more "A Whirlwind Tutorial on
Creating Really Teensy ELF Executables for Linux"
([http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...](http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html)).
Last time I checked, the teensy executable had stopped working around Linux
2.6.26 or 2.6.27, and I don't know why.

Relatedly, I wrote a tiny quasi-Forth in itself that generates ELF executables
directly at <https://github.com/kragen/stoneknifeforth>. Its executables also
stopped running around Linux 2.6.27, and I still haven't bothered to figure
out why.

~~~
breadbox
That's odd. I'm currently running 2.6.32, and it's working fine for me. Maybe
it was a transient problem?

Feel free to email me if you notice any of the teensy executables not working.
I don't follow the bleeding edge very closely, but I do make a serious effort
to keep all of them working.

~~~
sparky
Works on 3.2.0 too. I do get:

    
    
      ~$ file a.out
      a.out: ELF 32-bit invalid byte order (SYSV)
    

But that's probably to be expected, given how close to the edges of the ELF
spec it treads :)

------
ChuckMcM
One of the cool things about "personal computers", when they were not
synonymous with "IBM PC" or x86 box, was that you had total control over every
bit and byte that went into them. Sometimes you had to use switches to
manually set memory contents, sometimes there was a hard coded 'boot loader'
which would do that for you. The coolest demo I think I've seen in this space
was an FPGA computer design where the first download into the FPGA made it a
serial device that could write memory, and then you erased that and loaded a
computer which would then read that memory and execute it.

I believe that one of the reasons the Arduino has the appeal it does is
because you can know everything there is to know about the program it is
running. That is a lot of fun for a technologist.

It would be fun to have this blog posting written from within a debugger. I
always found it intriguing to 'debug a program into existence' as it were.

~~~
kunai
It's kind of the same deal now with the Raspberry Pi, except for the fact that
it uses RISC and not x86. It's a great tinkering platform.

Now, if only somebody would make a ring-0 OS for ARM... Now THAT would be fun.

~~~
pjmlp
You mean like Active Oberon?

<http://www.ocp.inf.ethz.ch/wiki/>

Not sure how workable this version is, but you can check on the forums,

ftp://ftp.lrz.de/transfer/BlueBottle-A2/ARMRelease.zip

You just need to enjoy using Pascal syntax languages for system programming.

------
kunai
So essentially, this is writing an application in machine code?

This is so fascinating I'm starting to get palpitations. I've always wanted to
know how to program in machine code. I've looked through the web countless
times in search of something like this, and haven't ever found it, until now.

Thanks for the great insight. This kind of stuff makes C/C++ look like stuff
for total newbies. Getting this close to the hardware really is quite mind-
boggling.

~~~
femto
> I've always wanted to know how to program in machine code.

1) Decide which processor you want to program. I'm going to use a Z80, since
that's one I'm familiar with.

2) Get hold of a good book, making sure it includes a section that
exhaustively describes each instruction and the machine code for each. Eg.
"Programming the Z80" by Rodnay Zaks. The microprocessor's datasheet will
generally do if your familiar with other processors.

3) Read the book, cover to cover.

4) Make three vertical columns on a sheet of paper.

5) Write your program, in assembly language, in the middle column. Use
alphanumeric labels (label means variable name) for all addresses.

6) Decide at what address you want your program to start (the origin)

7) Write the numeric address in the left hand column, next to the first
instruction.

8) Look up the machine code, for the instruction in the middle column, in the
Zaks book.

9) Write the machine code in the right hand column.

10) Add the length of the instruction (# bytes) that you have just written
down to the address, and write the answer on the next row of the left hand
column. You might have to leave labels in place for instructions that refer to
parts of the program that you have not yet assembled.

11) Repeat from step 8, until the entire program has been assembled.

12) Go back and fill in the numerical addresses for any addresses that are
still labels.

13) Now you have to get the program in memory. We're going to assume that a
programming language, such as BASIC is available. The alternative is a keypad
with address/data entry functions and a method to get an initial value into
the program counter.

14) Create a big array, in BASIC, with all the numbers from the right hand
column.

15) Write a loop which POKES each numeric value into memory, starting from the
origin address.

16) Transfer execution to the origin address, using the a USR(nnnn)
instruction, where nnnn is the origin address.

17) Hopefully your program works, but if not, make changes and go back to step
4 until your program works.

Enjoy! In time, the process gets quicker, as you eventually remember the
machine code for the the most common instructions and don't have to refer to
the book.

If you're writing timing critical code, have a fourth column, in which you
record the number of clock cycles for each instruction to execute, and sum
those numbers to determine execution time. If you have a target execution
time, you will need to add/remove instructions to achieve the target.

~~~
ganley
If I had a nickel for every hour I spent doing this as a teen... (Sinclair
ZX-81, then TRS-80 Model 1.)

Also, that Zaks book rocks. To this day one of the best programming references
I've ever used. <http://www.z80.info/zaks.html>

------
drivers99
This is great. I've had low-level stuff on my mind lately. I was thinking
about where to start, either writing my own binary to the boot sector of a
disk, or booting up MS-DOS and going from there, or from linux or windows and
starting with machine code from there. So this would be perfect. (I was
thinking of maybe implementing FORTH. Interesting that kragen mentions a "tiny
quasi-Forth" that he made.)

------
Turing_Machine
We used to do it with toggle switches, back in the day (long before ELF
binaries existed, though).

~~~
groby_b
Well, only the boot loader. You could use paper tape after you had that keyed
in :)

~~~
femto
My favourite boot-loader story was told to me by one of the old-hands on the
Jindalee Radar, when it was still a research project. Jindalee had a manned
receiver station and a remote transmitter station, about 100km away. They were
connected via a radio link, and to start with, the PDP at the remote site had
to be booted by keying in the boot-loader over the radio link. If you lost the
radio link, you had to start again...and again... and again...

------
Joeboy
At some point soonish I intend to have a go at loading dynamic libraries in
bare metal on the Raspberry Pi. I'll be on the lookout for stuff like this for
.so's. Suggestions welcome.

------
ObnoxiousJul
I am voiceless: why would the f*ck would someone loose such that much time on
a trivial, yet annoying task?

That is the first lesson you have in assembly language: program in assembly
language, then in C because it spares you the time (and the mistakes involved
in the process) to do such a thing.

Thousands of men year efforts and wisdom ruined in a post, showing how people
have too much time on their hands, and so few imaginations (well he could have
written something interesting on how to display p0rn pictures in ASCII art at
least).

~~~
daeken
Having spent my years climbing up and down the ladder of abstraction, I think
your analysis is _way_ off the mark. This is a great way to learn how ELF
works (and binaries in general), learn how machine code is formed, etc. Is it
an actually 'useful' task, that produces a useful end product? Yes: knowledge.
Knowledge that isn't easy to acquire.

You won't ever do this in the Real World (TM), but it's a fantastic way to get
into things.

~~~
ObnoxiousJul
I studied physics, and I learnt actual programming and assembly language: I
actually did this in the real world!

What do you learn in Computer Science then?!

Gibbering useless concepts that makes you non-sensical experts in the field of
not delivering your software neither in time, nor in the frame of the
specification? Or just

~~~
adamnemecek
Why exactly does this article make you so enraged?

~~~
nullymcnull
Indeed. He's telling us much more about himself than he is anything relevant
to the article.

If you see nothing but a huge waste of time in this post, you're probably on
the wrong site. HN in its prime would have _really_ pissed you off, no
doubt...

