23 ms·
Asmttpd: Web server for Linux written in amd64 assembly (2017)
- k1ns 8y agoThis is really cool. I admire your bravery. I noticed that certain options are hardcoded (such as the port number). As someone with very little experience in assembly, how difficult would it be to make this dynamic via environment variables?
- haolez 8y agoThat's probably not a good model to fit in assembly code. It's easier to have a wrapper in another language as the launcher and have it set the variables in the assembly code and build the binary.
- getcrunk 8y agoWhy?
- SSLy 8y agofor starters, you'd need a text parser
- admax88q 8y agoSomething you already have if you're building an http server in asm...
- haolez 8y agoI’m assuming that there is a need to dynamically configure things like the port in the parent’s environment. However, for an assembly tool, it might make sense to simply have it hard coded and save the extra complexity. My launcher script suggestion is a possible solution to this, but I would just hard code the port and ship it without a launcher myself. The suckless projects make use of hard coded configurations in their C programs. The principle is the same.
- kjeetgill 8y agospeculation: Maybe it's simpler to just bake a string into the binary and hardcode the pointer to at every use than futz around with strings in asm? But if you're already doing the rest of it in asm why would that scare you?
- captoblivious 8y agoA wrapper that recompiles every time you run or change an option? lol. HN has caught the reddit cancer. environment variables are after argv. http://asm.sourceforge.net/articles/startup.html#st http://asm.sourceforge.net/articles/startup.html#st
- saagarjha 8y agoWhile the point you are making is correct, you could have presented it in a less abrasive way. Not everyone is aware of how environment variables are passed to programs, or pieced together that char envp is also available in assembly.
- alxlaz 8y agoIf we're talking about bad ways to present knowledge, the parent comment could also have been "I really don't know much on this topic so I'd rather not speculate" ;-).
- jxub 8y agoWell, it's not mine but I'm sure it certainly was quite a challenge to build, props to the author for accomplishing that.
- alxlaz 8y agoIt wouldn't be that difficult, it would only require some libc-related magic (but I haven't read much of the asmttpd source code to know how much of it is in there). IIRC, environment variables are passed from the parent process to the child in the form of a "naive" array of strings, so the truly unpleasant parts of this, like parsing text from a config file, are already taken care of.
- tormeh 8y agoSlightly off topic, but I don't get environment variables. To me they look like implicit options that are based on what shell session you're currently in. Stuff that hangs around waiting to kill you when you're not looking, like a cecum. Why would anyone want environment variables when you can have config files or explicit options instead?
- tlarkworthy 8y agoI am very pro environment vars and consider files an anti pattern. Files are like globals, sibling processes end up sharing state, plus they survive longer than their use case. Env variables cascade, which is why they have wider uses than program args. You can organize a system as a group of processes and envs are a good way to share state and abstract out the details like prod vs staging without affecting the program implementation.
- kjeetgill 8y agoI'd say it's really about size. A few dozen configs in environmental vars, sure. But once you expand beyond that, need to manage variants of them, need to compose them from fragments you start to see benefits from something more structured like xml, toml, json, or yaml etc.
- tlarkworthy 8y agoI just start loading env variables from files, e.g. source blah.env This way, my bash environment mirrors the task I am working on
- ConcernedCoder 8y agoI'd say it's really about size. My wife assures me that size doesn't matter, it's actually the way you use your configs to manage your environmental vars. (sorry, I just couldn't help myself...)
- gpderetta 8y agoEnvs are also globals. Dynamically scoped globals. They are evil and allow all kind of spooky action at distance, but sometimes they are a necessary evil.
- sctb 8y agoA couple of past threads: https://news.ycombinator.com/item?id=9571827 https://news.ycombinator.com/item?id=9571827 https://news.ycombinator.com/item?id=7170010 https://news.ycombinator.com/item?id=7170010
- daniel-cussen 8y ago25.8 KB zip file! Now that's tight code.
- vbezhenar 8y agoI'm not sure that properly written C version would have bigger size (assuming that unnecessary code is stripped, of course).
- Drdrdrq 8y agoCurious: how does Rust cope in this regard?
- estebank 8y agoThey're on the bigger side, due to a combination of defaulting to static linking, some optimizations not having been possible (ThinLTO comes to mind), lots of debug strings and metadata, as well as the use of jemalloc[1][2]. [1]: https://jamesmunns.com/blog/tinyrocket/ https://jamesmunns.com/blog/tinyrocket/ [2]: https://users.rust-lang.org/t/rust-binary-sizes-once-again/16287 https://users.rust-lang.org/t/rust-binary-sizes-once-again/1...
- kbenson 8y agoYou're talking binary size, the zip file being referred to is the entire git repo in zip format. How large the Rust code would be is an interesting question. Interestingly, the repo notes the binary is only 6kb. I doubt C or C++ will get anywhere close to that.
- saagarjha 8y agoIf they're downloading the zip file from GitHub, then no, the zip only contains a snapshot of the current master branch.
- Thiez 8y ago
- laurent123456 8y agoThat's impressive, but I couldn't find the reason for it. Was it done just for the challenge, or can their be a use for this kind of server?
- yjftsjthsd-h 8y agoIt's tiny; might have embedded use?
- stingraycharles 8y agoDefinitely looks like it. No library dependencies such like libc, makes it an ideal use case for embedded software.
- tambourine_man 8y agoEmbedded x86_64? Is that a common thing?
- alxlaz 8y agoIt's quite common. "Embedded" doesn't mean just "low power and little number crunching ability", it's just a fancy way of saying "special purpose". E.g.: https://buy.advantech.com/Industrial-Computers/Fanless-Industrial-PCs/model-MIC-7700H-00A1.htm https://buy.advantech.com/Industrial-Computers/Fanless-Indus... is an industrial computer; https://www.edge-core.com/productsInfo.php?cls=&cls2=&cls3=15&id=1 https://www.edge-core.com/productsInfo.php?cls=&cls2=&cls3=1... is a "whitebox" switch, but it's a representative of many OEM/ODM designs. x86-64 is a great architecture for many applications. It's cheap (due to volume), well-understood, has great compatibility, and is pretty much the best-supported architecture when it comes to software. Edit: that being said, no, this doesn't have any embedded use today. Embedded x86 isn't 386 processors anymore. The typical scenario for an embedded x86-64 is "I need to drive this specific application and I want to leverage the Linux/FreeBSD/Windows environment for programming". That already puts you way ahead of the point where writing assembly code is useful performance-wise, and you probably don't want to put ASM code you downloaded off the Internet in a network-facing position :-).
- fbn79 8y agoAVE CESARE!
- saagarjha 8y ago%macro stackpush 0 push rdi push rsi push rdx push r10 push r8 push r9 push rbx push rcx %endmacro %macro stackpop 0 pop rcx pop rbx pop r9 pop r8 pop r10 pop rdx pop rsi pop rdi %endmacro I guess that's one way of saving registers. Not particularly efficient, I guess, but it works…
- agumonkey 8y agoI wonder if there are cpus with 1-instr state save ps: thank you all for the answers
- blattimwind 8y agoSure. It's called windowed registers and you have one instruction each to move the window right/left.
- saagarjha 8y agoEven if there was one, you'd still be saving registers unnecessarily. If you only clobber one register in a procedure there's no need to save and restore all of them.
- kijiki 8y agox86 has LOADALL and SAVEALL. https://en.wikipedia.org/wiki/LOADALL https://en.wikipedia.org/wiki/LOADALL
- msla 8y agoThose undocumented instructions don't exist on x86_64, and they could be used to do bizarre things on the processors which had them: > As the two LOADALL instructions were never documented and do not exist on later processors, the opcodes were reused in the AMD64 architecture.[8] The opcode for the 286 LOADALL instruction, 0F05, became the AMD64 instruction SYSCALL; the 386 LOADALL instruction, 0F07, became the SYSRET instruction. These definitions were cemented even on Intel CPUs with the introduction of the Intel 64 implementation of AMD64.[9] [snip] > Because LOADALL did not perform any checks on the validity of the data loaded into processor registers, it was possible to load a processor state that could not be normally entered, such as using real mode (PE=0) together with paging (PG=1) on 386-class CPUs.[7]
- mabynogy 8y agoNobody mentioned rwasa so I do it (an HTTPs webserver written in asm): https://2ton.com.au/rwasa/ https://2ton.com.au/rwasa/ I proposed to debian (on an IRC channel for that) to make a package for rwasa but I've been told that "nobody does asm in 2017". I wonder if it's still true in 2018.
- M00nF1sh 8y agoFYI: nobody does asm in 2018
- shakna 8y agoThere are still programs available in Debian written in asm, but they tend to be exceptional. Picolisp 64bit Luajit (mostly)
- lispre 8y agoReally? Picolisp was build with asm? not C as SBCL
- shakna 8y agoPicolisp 32bit is C, but 64bit is asm. There is also Ersatz Picolisp which is Java. All sources are really well outlined, and worth the read through. But you might start with the 64bit's README. [0] [0] https://software-lab.de/doc64/README https://software-lab.de/doc64/README
- anyfoo 8y agoNeat, but unless I am missing something, a nightmare in terms of security. Assembly has a worse type system than even C: essentially no type system at all! (Or rather the weakest, simplest, most dynamic type system you can imagine.)
- nickpsecurity 8y agoThere has been a lot of work on that. Look up Typed Assembly Language, Security in front of that, and Dependently-Typed Assembly Language. Here's one that was integrated with a safe, C variant. https://www.cs.cornell.edu/talc/ https://www.cs.cornell.edu/talc/
- anyfoo 8y agoWow, even dependently typed, that's pretty brilliant. I can see this being enormously helpful when writing very low level, for example early boot stage, assembly code.
- ChickeNES 8y agoUnfortunately it appears that the linked project is not free software :(
- nickpsecurity 8y agoI have the source but you're right: no obvious license file. I might email them about it.
- userbinator 8y agoOn the other hand, there is essentially no undefined behaviour, no chances of compiler bugs/backdoors, and the code is (by necessity) simple enough that what it does can be easily analysed and understood. Not a lot of places for bugs, security or otherwise, to hide if there's not a lot of code in the first place.
- nickpsecurity 8y ago
- bumholio 8y agoSounds like an excelent front end, for best performance. For the back end stability is paramount, that's why I would always recommend to pair this with a shell script server: https://github.com/avleen/bashttpd https://github.com/avleen/bashttpd Bash is undeniably the language with the highest possible stability, you can literally feel the stability and security when a file is served and the hard drives go crazy.
- tptacek 8y agoIsn't this basically a web server for Linux written in C, except with absolutely no standard library optimizations? Yes, it's assembly, but it's basically a thin script over a set of string library functions which are themselves just naive versions of what's already in libc. Most of this is just strcpy/strcat/strchr/strstr; the only reason it's not one giant stack overflow is that it doesn't actually implement most of HTTP (for instance: nothing reads Content-length, and everything works off a static buffer that is sized to be as large as the maximum request it will read). What's the point of writing assembly if you're going to repeatedly scan to the end of strings as you try to build them? I'm not taking away anything from the project as an exercise. It's neat! But like: it's not something you'd ever want to use, or a productive path to go down to make a good webserver.
- 1996 8y agoI do not care about good. I care about good enough. I would want to use that, on systemd nspawns (or whatever the current name of systemd container is) to see if I could get more performance than nginx for APIs returning fixed length things. I wonder how efficient it would be to spawn a few hundreds.
- saagarjha 8y agoAs I've mentioned in another comment, I wouldn't place any bets on the efficiency of this code. It's written with easy of understanding in mind at the expense of code size and speed.
- userbinator 8y agoWhat's the point of writing assembly if you're going to repeatedly scan to the end of strings as you try to build them? I'd have to benchmark to make any claims about speed, but from my past, quite extensive experience with using Asm, it's not uncommon for even a simple/naive/asymptotically less efficient algorithm written in Asm to outperform a more complex/clever/asymptotically efficient one in an HLL at the problem sizes encountered in practice, simply by virtue of the constant factor being much smaller. For the same reason a bubble/insertion sort in Asm can easily beat the standard library sort if your inputs aren't that big. Of course if you combine Asm with efficient algorithms (which can sometimes be easier to write than in a HLL), then you can get much closer to how much the CPU can actually do.
- inamberclad 8y agoThis is some of the best written assembly I've seen. I can actually follow what's going on.
- ebikelaw 8y agoLooking at the code I’d be surprised if this is anywhere near as fast as a simple equivalent written in C++ (which wouldn’t be as pessimistic with the register saving, in an opt build) or even compared to bozohttpd.
- ConcernedCoder 8y agoNice? I mean, how would you be certain it was NOT a "Web VIRUS for Linux written in amd64 assembly (2017)" unless you could read grok asm? NOTE: I'm not saying it IS or ISN'T, and although I CAN grok asm, I'm not going to take the time to do it right now... Just struck me as possible, given the idea of a high-level language is to mainly provide abstraction over implementation details ( point being, you can't really get any MORE implementation detail specific than asm... ) (edit: words...)
- saagarjha 8y agoWell, how do you know the C library you just downloaded isn't a virus either?
- crazy_monkey 8y agoThis sounds super secure. :/