5 ms·
> Linux is 32-bit, runs in protected mode, has flat memory model, and uses the ELF format for binaries. Well, that's a touch out-of-date :) All the same, I do
by halosghost 11y ago
> Linux is 32-bit, runs in protected mode, has flat memory model, and uses the ELF format for binaries.
Well, that's a touch out-of-date :)
All the same, I do find it fun to see the set of articles recently trying to show modern programmers that assembly isn't as terrifying as people make it out to be. My own opinion is that, though asm tends to be a bit more verbose and tedious than other higher-level languages, it looks like it's also dramatically simpler in a lot of ways.
For examle, the Heavything[1] library from 2ton suggests to me that asm can still be used for high-performance applications today.
Good find and a fun read!
[1] https://2ton.com.au/HeavyThing/ https://2ton.com.au/HeavyThing/
- 2ton_jeff 11y agoThanks for that, and a tip of my hat to the HN community. Love this place. Having written the aforementioned, I thought maybe y'all would be interested in a very very lightweight version of same done w/ my assembler of choice (only because it reminds me of Turbo Assembler from way back in the day). format ELF64 executable _start: mov eax, 1 ; syscall # = write mov edi, 1 ; man 2 write arg1 == our fd, stdout mov esi, .msg ; "" arg2 == const void *buf mov edx, .msglen ; "" arg3 == size_t count syscall mov eax, 60 ; syscall # = exit xor edi, edi ; man 2 exit arg1 == status syscall .msg: db 'Greetings, HackerNews!',10 .msglen = $ - .msg I don't think it gets much clearer or simpler than that, and more so that "man 2 xxx" provides all of the information you need for syscall goods anyway, it really isn't that bad :-) if you compile this with fasm (http://www.flatassembler.net/ http://www.flatassembler.net/) it produces a 174 byte ELF64 (and if we wanted to have some fun, we could lower that number by quite a bit still). Cheers! Edit: leading spaces for code
- oso2k 11y agoLike markdown, 3+ leading spaces. mov rax, 0xdeadbeef
- 2ton_jeff 11y agoMuch nicer, thanks!
- monocasa 11y agoWait, ELF64 and a pointer going into a 32 bit register?
- 2ton_jeff 11y agoBy default all code/RIP addresses are <32 bit, no harm no foul.
- userbinator 11y agoand if we wanted to have some fun, we could lower that number by quite a bit still The most "immediately" (pun intended) obvious size optimisation would be to do this: push 1 pop eax mov edi, eax ... push .msglen pop edx ... push 60 pop eax ...which should save 9 bytes. Note that 174 bytes is still a far ways off from the equivalent under DOS, which would be... 95 BA 07 01 CD 21 C3 47 72 65 65 74 69 6E 67 73 2C 20 48 61 63 6B 65 72 4E 65 77 73 21 0D 0A 24 ...these 32 bytes, 25 of which is the message itself.
- JoshTriplett 11y ago> and if we wanted to have some fun, we could lower that number by quite a bit still One of my earliest introductions to the ELF format was "A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux" (http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...), which I still highly recommend.
- 2ton_jeff 11y agoThis is a beauty, thanks for sharing! I second the recommendation.
- halosghost 11y agoYou're more than welcome, I was astounded by your great work when I saw it on the HN frontpage a week or two ago. Since then, I have packaged heavything's whole showcase for Arch[1] (mainly because I'm quite interested in using rwasa for my own website but also so that other Archers may reap the benefits as well). Keep up the awesome work! [1] https://aur.archlinux.org/pkgbase/heavything https://aur.archlinux.org/pkgbase/heavything
- jawr 11y agoFrom a beginners point of view, what's the benefit of fasm over gas?
- cbd1984 11y agoIt also uses the int 0x80 interface instead of the faster sysenter opcode. (AMD calls this opcode syscall.) http://wiki.osdev.org/SYSENTER http://wiki.osdev.org/SYSENTER I say "faster" above, and that's true for all chips since the Pentium 4, if not earlier, but it isn't true on all 32-bit x86 chips. It isn't even true on all 32-bit x86 chips which have the opcode. So the Linux kernel has a special trick such that all binaries always use the fastest syscall method, regardless of which kind of system they were compiled for: linux-gate.so.1 also known as linux-vdso.so.1 This isn't actually a file on disk, it's just some machine code the kernel maps into the process address space which syscalls indirect through, because the kernel knows more about the hardware than applications. http://www.trilithium.com/johan/2005/08/linux-gate/ http://www.trilithium.com/johan/2005/08/linux-gate/ vDSO even stands for virtual Dynamic Shared Object: http://man7.org/linux/man-pages/man7/vdso.7.html http://man7.org/linux/man-pages/man7/vdso.7.html Aside from being virtual, it's a normal ELF shared object, with symbol names and versoning and the functions use the normal C calling convention.
- 2ton_jeff 11y agoOn my list of things to do is to write an article titled "VDSO and why you should care." Interestingly, syscall indirection isn't among my reasons (maybe I am too comfortable in my SSE2+ x86_64 environment). If anyone is interested, the magic all lives in /proc/self/auxv, and my own library implementation to hook gettimeofday can be perused at: https://2ton.com.au/library_as_html/vdso.inc.html https://2ton.com.au/library_as_html/vdso.inc.html