
Echo – Assembly program that prints the first positional argument to stdout - activatedgeek
https://github.com/kelseyhightower/echo
======
aiur3la
Serious question: why is this on HN front page? Am I missing something?

~~~
Bladtman
Serious answer: Because many developers regard assembly as some sort deep
magic only understood by elder gods. This, of course, comes from some vague
(and not entirely correct) understanding of "assembly" running beneath
everything else, and thus being fundamental, yet not immediately useful to a
large category of developers today. Hence it seems important but archaic.
Archaic + difficult = elder knowledge.

~~~
userbinator
I've actually had a few coworkers think I'm some sort of elder god when I find
the root cause of subtle bugs that would've either required deep knowledge of
the C++ standard, or not-as-deep knowledge of Asm. These are bugs that others
have spent many hours staring at the source and stepping through in a debugger
without any better idea of why they occur, but are solved in minutes by a
glance at the Asm. IMHO if you are working with native code at all, it's a
very useful skill to have.

~~~
ycmbntrthrwaway
Once you are tired being praised, teach them some valgrind. It will solve most
of their problems.

~~~
userbinator
I'm pretty sure the bugs I found would not have been valgrind-able as they
were unrelated to memory errors.

~~~
ycmbntrthrwaway
From my experience most of the hard to trace errors come from uninitialized
variables and they are usually valgrindable. It is VM-based so it can cache
jumps and other conditions that depend one uninitialized vars via taint
analysis.

------
__michaelg
It looks like Kelsey didn't write a lot of assembly before. There are quite a
few things you either wouldn't do -- like `cld` for no reason -- or most
people (and compilers) would do otherwise -- e.g., `xor ebx, ebx` instead of
`mov ebx, 0`.

Besides, 32 bit (⊙＿⊙')

~~~
kelseyhightower
Yes, this is my first assembly program. I had to look up every instruction and
it took me hours to understand even the basics, but it was worth it. I have a
much better understanding of x86 assembly and plan to write larger programs to
continue learning in 2017.

I went with 32 bit because all the examples were 64 bit so I forced to learn
the nasm and ld flags to get my program to compile, link, and run. I also
learned a lot about the different registers available to 32 and 64 bit
programs.

------
jamesfisher
The instruction `repne scasb`[1] stood out. `repne X` means "while (not equal)
{ X; }". How is `repne` implemented? Is `repne scasb` assembly shorthand for a
`scasb` then a `jne`? Or is `repne` some fancy higher-order instruction which
takes another instruction as its argument?

[1]:
[https://github.com/kelseyhightower/echo/blob/53d84ea4e79db3d...](https://github.com/kelseyhightower/echo/blob/53d84ea4e79db3dbe27688b5d45d839854851a57/echo.asm#L32)

~~~
Stratoscope
The latter. The various REPxx prefixes cause a string instruction like SCASB
to be repeated until some condition is satisfied.

These date back all the way to the 8086/8088\. They were the fastest way to do
string operations on those early CPUs, but I don't think this the case on
modern CPUs.

[https://www.google.com/search?q=intel+rep+prefix](https://www.google.com/search?q=intel+rep+prefix)

[http://wiki.osdev.org/X86-64_Instruction_Encoding#REPNE.2FRE...](http://wiki.osdev.org/X86-64_Instruction_Encoding#REPNE.2FREPNZ.2C_REP_and_REPE.2FREPZ_prefixes)

[https://courses.engr.illinois.edu/ece390/archive/spr2002/boo...](https://courses.engr.illinois.edu/ece390/archive/spr2002/books/labmanual/inst-
ref-scasb.html)

~~~
tptacek
They're still the x86-64 implementation for things like strlen on a bunch of
platforms. They're not always the fastest, but have code size advantages.

[http://agner.org/optimize/optimizing_assembly.pdf](http://agner.org/optimize/optimizing_assembly.pdf)

~~~
Stratoscope
That's a really interesting document - I am going to spend some time studying
it, thanks!

Good point about the code size. I imagine there are likely to be cases where
that would let some algorithm run faster overall because it fits in the
instruction cache, even if the string operation considered on its own is
slower.

------
bdcravens
I'm curious as to the why. Kubernetes doesn't keep Kelsey busy enough? :-)

~~~
mistaken
I guess it's because the echo command included in the shell was slow.

~~~
pm215
The cost of fork+exec of a separate binary will make even the most efficient
possible external echo slower than the shell builtin, I suspect. (This is why
echo is a builtin in the first place, though there's no requirement for it to
be so.)

------
whym
The source code includes this notice: "Copyright 2017 Google Inc. All Rights
Reserved."

I wonder if the couple of dozens of lines of assembly code could be trivial
enough to be public domain. Assuming a straightforward implementation, surely
there is far less freedom in expressing the simplest version of the echo
program in ASM compared to, say, C?

~~~
userbinator
_surely there is far less freedom in expressing the simplest version of the
echo program in ASM compared to, say, C?_

I'd say it's the opposite, since it is often the case that more instructions
(and thus ways to select and arrange them) are required to express an
operation in Asm compared to an HLL like C. This implies that there is room
for more creativity when e.g. writing a "Hello world" in Asm vs. C.

------
wfunction
Doesn't echo print all the arguments?

~~~
kelseyhightower
It will as I continue to work on echo until it's "finished". This is the
result of 4 hours of learning and writing my first assembly program.

------
tlholaday
echo returns nonzero if it cannot write ...

touch foo.txt; chmod 400 foo.txt; echo ouch > foo.txt; echo $?

.., but it appears this asm returns zero always.

~~~
tomjakubowski
How do "raw" system calls pass back error information on Linux? errno is
strictly a C/POSIX abstraction, right?

~~~
dom0
They just return the negative error number.

Eg. -EINVAL.

~~~
JoshTriplett
And for syscalls that also have a meaningful return value, the ABI requires
that valid errno values fall in the range -1 to -4095, to disambiguate them
from any possible return value. Those values can't conflict with valid
userspace pointers (since they'd point into kernel space), and syscalls must
not allow them to conflict with valid numeric return values.

------
andreiw
Now rewrite in IR =))

