
Go and Assembly - cdoxsey
http://www.doxsey.net/blog/go-and-assembly
======
charlieflowers
Now _this_ is an impressive argument. Particularly the first section about the
tool chain (and the assembly part is really cool too).

I have been holding back because I don't like the lack of exceptions. But it
occurred to me that C doesn't have anything like exceptions either, and even
though that lack causes some serious irritation, the C language as a total
package overcomes it and is really powerful.

I don't know if any language can beat that list of tool chain benefits. Maybe
I _will_ give go a whirl.

~~~
geoka9
I think the only thing missing is a REPL as part of the tool chain. ipython
and scala shell are so useful, especially when you're learning or just testing
things out.

~~~
cerales
Agreed. The way I tend to use the repl in clojure is just to code up a script
in vim and then %Eval the whole thing. Editor plugins for Go could compile-
and-run, and know stuff like the working directory and the gopath, which could
get you a bit closer without having to build a real REPL.

~~~
dualogy
> Editor plugins for Go could compile-and-run

Yep, rolled my own here: <http://github.com/metaleap/go-buildrun> \-- I use it
with GoSublime on Ctrl+B (which I strongly suspect must have some repl-like
feature anyway by now, but not sure) -- but works in any editor that lets you
hook a key binding to an executable and pass it the current .go file's path.

------
WalterBright
Here's how to do inline assembler in D:

    
    
        int *_memset32(int *p, int value, size_t count) {
          asm {
            mov     EDI,p           ;
            mov     EAX,value       ;
            mov     ECX,count       ;
            mov     EDX,EDI         ;
            rep                     ;
            stosd                   ;
            mov     EAX,EDX         ;
          }
        }
    

The compiler adds the function prolog/epilog for you, as well as any
save/restore for used registers.

~~~
strmpnk
Well, this article wasn't about _inline_ assembler. Regardless, inline forms
have a number of problems, the biggest one being supporting multiple platforms
w/o a bunch of preprocessor noise. That doesn't stop it from being useful for
certain languages but it matters less and less given how compilers behave
these days.

~~~
WalterBright
There is a steady drift away from using assembler even in languages that
support it. Intrinsics, for example, often work better. But there are a few
things where it really comes in handy.

~~~
strmpnk
I wonder if we'll see more user-side emulation of intrinsics given new
__attribute__ flags compilers are implementing. It certainly is easier to
reason about.

Go doesn't have anything like that yet but I wouldn't be surprised if an
experimental implementation is done by one of the alternate compilers being
worked on.

------
dualogy
Great write-up. As I'm perusing the math/somefeature_arm.s and
math/somefeature_amd64.s files in Go's math package, I can't help notice most
of them look like this:

<http://golang.org/src/pkg/math/remainder_arm.s>

That is, very short code that just looks like a function call to me, the
complete asm noob. What is it, are all these maths functions implemented in
hardware by amd64 and arm architectures? Or is this "asm code" just reverting
to calling the Go implementation of the particular function (aka the not
really that "optimized")?

~~~
cdoxsey
In this case there is a 386 implementation:

<http://golang.org/src/pkg/math/remainder_386.s>

The other two call the go version:

<http://golang.org/src/pkg/math/remainder.go>

~~~
dualogy
Yeah that was kinda my point ;)) so basically 386 users get some highly
specialized hand-tuned asm optimization whereas arm and amd64 merely get a
commoner's gc treatment -- or am I missing something? ;)

~~~
stephencanon
Several things:

\- The fprem1 instruction is actually a long microcode sequence and is quite
slow; 26-50 cycles on SNB according to Agner Fog. Several iterations of that
loop are necessary for a complete reduction of some operands.

\- There is no analogous instruction on arm (or really, any platform that
isn't x86), anyway.

\- If you're using the floating-point remainder operation in a performance-
sensitive context, You're Doing It Wrong. Programmers have gotten so used to
this that there is little value in optimizing remainder; it is rarely used in
situations where the optimization would matter.

~~~
dualogy
This was just a random example I picked, I'm not using that function
currently. But let's just say abs(), sin(), cos()...

------
freehunter
And herein lies the problem with Go. Seriously, try searching for articles
about Go on HN. People always say "well the name isn't a problem, because you
just search for it with "golang" instead!" but _no one writes golang unless
they're pointing out how to search for it_. If I was trying to get back to
this article a month from now and I searched for "go", would I find it?
Probably not, unless I remembered the article title contained the word
"assembly", but then I'm matching a search to assembly and not Go.

The name is a problem. And if the name is not a problem, then the community is
a problem.

~~~
dualogy
[[[EDIT: wrote this little rant before realizing you specifically refer to HN
search rather than general search. Yeah why would I ever search on a specific
Go topic exclusively on HN, instead of web-searching?]]]

Every time a Go article comes up, the "name searchability" discussion comes
up. Go's been around for some 4-5 years now, can we all come to terms with its
name?

Somehow whenever brainfuck-lang threads show up, this issue is never raised,
but surely might exist just the same? What about Perl (a common word), or
Basic (even more basic), heck "C" (a freakin' letter). Is that so much better
for searchability? Rust -- a common word. D -- a freakin' letter. Miranda -- a
language but also the name of 100s of townships, an IM client etc etc.

Go is not the first language to have this "problem", and in fair daily
practice it never ever is a problem. Because you never search for Go, you
search for "Go channels" or "Go image processing" or "Go GTK binding" or "Go
compiler error X" etc. etc. Like you would for all these other fine examples
of oddly named languages. And somehow, Google is semantically smart enough to
present a few decent matches among the first 10, even with all your
personalization & tracking cookies etc. etc. disabled.

So... problem? Herin lies the problem with Go? Seriously... it's just not a
big freaking deal getting in the way of getting stuff done. Promised.

~~~
TylerE
Your examples make no real sense, other than "Basic". Perl is absolutely NOT a
common word. _Pearl_ is common, but Perl is the programming language (only)

~~~
dualogy
zOMG you're right re pearl -- I'm kinda shocked at myself right now. In my
defense, in German it's "Perle" so not that different...

OK scratch the Perl example. Still standing by my point: it's a "problem"
shared by many languages and it's not a problem in the first place.

~~~
TylerE
I found a list of English words by frequecy of use in Project Gutenberg texts.

"Basic" is around #9,500.

"Rust" is ~#10,950

"Java" doesn't appear at all (List goes out to 40,000) (Admittedly, somewhat
biased by the dated-ness of the material, but it's still not a common one.)

Go is #106, and modern lists based on contemporary sources place it in the top
50 most used English words.

~~~
Jabbles
<http://norvig.com/mayzner.html>

(1MB) word count list: <http://norvig.com/google-books-common-words.txt>

Go: 187, Basic: 759, Java: 7136, Rust: 13110

With relative frequencies 320M:103M:8.9M:3.6M ~ 100:30:3:1

~~~
sirclueless
This is very biased, because there's a whole junkload of intro-to-java
textbooks in Google books.

[https://www.google.com/search?q=java&btnG=Search+Books&#...</a>

------
damien
So what does that middle dot actually do before the function names? It doesn't
seem to be mentioned in the linked documentation of the Plan 9 assembler, and
if I have to use a character that I can't easily type with my keyboard, I'd
like to at least know what it actually does. :)

Also, doesn't doing this limit your code to using gc toolchain (since the
generic Go function has to get called from the arch-specific asm code which
uses that Plan 9 dialect)? Does this mean that the Go standard library can't
be compiled with gccgo for example?

~~~
mseepgood
> So what does that middle dot actually do before the function names?

<http://stackoverflow.com/a/13490787>

<http://article.gmane.org/gmane.comp.lang.go.general/78328>

------
pbsd
Does Go only support that crazy Plan 9 (amd64) assembler syntax that nobody
uses anywhere?

~~~
vanderZwan
Well, since two of the original three developers (Pike and Thompson) were part
of the Plan 9 team, it makes perfect sense that they based the compilers on
the Plan 9 ones.

~~~
cpeterso
I see recent commits in Go's mercurial history to fix bugs on Plan 9. Is
anyone at Google actually using Plan 9 to develop Go? Or is building for Plan
9 just a sanity test for maintaining cross platform code?

Wikipedia says the last "stable" release of Plan 9 was in 2002, but there seem
to be a number of recent forks.

~~~
4ad
Plan 9 is on a rolling release since 2002.

------
justsomedood
This reminds me of a topic that had come up earlier last year: Intermitten
problems with 32bit programs in go. If I remember correctly programs would
crash intermittently if the initial 512MB memory block requested wasn't
contiguous. Does anyone know if this still is the case? Is the solution still
to always just use 64bit?

~~~
dualogy
As I'm only on 64b right now, I can't quite remember whether that was fixed by
1.0.3 or will be in 1.1 -- but I'm pretty pretty sure one of these is the
case.

------
Xeoncross
That is pretty neat. I'm glad he mentioned that the Go compiler will not
inline functions written in assembly, but it will inline small Go functions.

~~~
dualogy
Yeah but the list of restrictions preventing inlining is pretty exhaustive...

~~~
georgemcbay
This is true currently but both the inlining and the garbage collector have
improved tremendously over the past year and should continue to get better.

I do wish Go supported an explicit inline modifier that worked like haxe's
though (unlike the C/C++ one which is more of a suggestion).

~~~
pcwalton
Most C dialects (for example, GCC and Clang) provide some form of explicit
inline qualifier that forces inlining, for example
"attribute((always_inline))".

------
csense
This assembler is awful. I thought that AT&T had a monopoly on ghastly
assembly language syntax -- but this article causes me to question that
assumption:

    
    
      MOVL BX,autotmp_0000+-4(SP)    ; from the article -- terrible!
      MOV EBX,[ESP+autotmp_0000-4]   ; Intel -- comprehensible!
    

This assembler has an imaginary register called FP.

WTF is up with the center dot?

A programming language should _not_ require Unicode to write -- _especially_
assembly language!

I don't know what's worse: That this assembler exists, or that a project chose
to use it after better alternatives had been created!

~~~
reinhardt
It's amusing that the first line is considered "terrible" but the latter is
"comprehensible". For someone versed in modern languages they both look like
gibberish.

~~~
csense
Here's an explanation suitable for someone only familiar with high-level
languages:

MOV x,y translates to the assignment operator "x = y" in a high level language
[1].

Your program only has access to one giant array called "memory" [2] [3]. So
MOV EAX,EBX means "EAX = EBX" in high-level terms; MOV EAX,[EBX] means "EAX =
memory[EBX]" in high-level terms ("memory[EBX]" has the same meaning here as
in C-family languages like C, Java, Javascript and Python). This choice of
operator notation is intuitive, because it's very similar with the use of
brackets in other popular languages.

The insane syntax uses parentheses instead of brackets. Which is confusing,
since it's _not_ related to the standard meaning of parentheses, grouping for
order of operations or function call. So you would say "MOV EAX,(EBX)" in
weird-syntax land.

But the insanity doesn't end there.

In the sane Intel syntax, if you want to load the value at memory location 148
+ -4 + ESP into EBX, you can probably figure out how you would say it:

    
    
      MOV EBX,[148 + -4 + ESP]
    

The C/Java/JavaScript/Python translation is:

    
    
      EBX = memory[148 + -4 + ESP]
    

In weird-land, the syntax for this operation is:

    
    
      MOVL BX,148 + -4 (SP)
    

To me, it looks like this instruction says:

    
    
      Let t = 148
      Let u = The contents of memory pointed to by SP
      Let v = -4*u
      Let BX = t+v
    

Clearly, there are only two possible explanations for this: The person who
came up with this syntax was drunk at the time, or the person who came up with
this syntax was high at the time.

[1] In a HLL, "x = y" allows arbitrarily long expressions for x and y, but in
assembly language only a few different forms of x and y are allowed. In a
high-level language, in the expression "x = y", x needs to be an lvalue, while
y can be a more general rvalue. "a = 5+6" is legal; "5+6 = a" is not. Both the
left- and right-hand side can be arbitrarily long and complicated, for example
the LHS could be "a.b.c.d.e.f.g.h" and the RHS could be "m+n+o+p+q+r+s+t",
assuming the appropriate variables exist and have the appropriate types.

[2] Unless you use multiple segments. But you generally don't do that.

[3] Or paging. But you usually let the OS take care of that.

------
tel
Why the \cdot? Is Unicode required to parse assembly?

~~~
vanderZwan
"Source code is Unicode text encoded in UTF-8."

<http://golang.org/ref/spec#Source_code_representation>

Historical reason, TL;DR edition: Plan 9 based compilers, because Ken
Thompson.

EDIT: see also mseepgood's response:
<http://news.ycombinator.com/item?id=5185334>

------
pjmlp
This is a nice example how to do low level programming while using a safe
strong typed language most of the time.

------
rartichoke
I only have 2 problems with Go.

1\. It does have its own package manager but good luck actually finding
packages. golang.org's list is out of date and so is every other resource.

This is a serious problem IMO.

2\. The third party web libs are pretty poor. I'm a big fan of Express for
Node and prefer just a little bit of goodies ontop of something minimal.

A lot of people like Sinatra/Flask so I'm not the only one who likes this.
There's nothing like this in Go.

We have the bits and pieces to make it but no one has stepped up. Right now
developing anything for the web with Go is just too annoying, you have to
create so many things that literally every other language has had solved for
years.

If both of these problems were solved I would insta switch to Go for
everything and never look back. It's just so pleasant to program in for all
the points you mentioned + more.

~~~
iand
Try <http://godoc.org/>

Because Go uses URLs for package names its easy to build tools like godoc.org
that automatically aggregate packages from the web.

~~~
rartichoke
It's a good start but it needs many more features to be considered usable. For
example, I just did a search for "redis" and about 30 libs came up. Half of
them don't even have a description.

How can I know which one to pick at a glance? Asking me to evaluate and
profile 30 different libs for just a single task is unreasonable.

Also this page isn't even on Google's first page for when you search for
something. I didn't even know it existed until you mentioned it.

~~~
jlgreco
How do you handle that with any other language? There is no shortage of redis
libs for any language.

~~~
flogic
If we look at CPAN
[http://search.cpan.org/search?query=redis&mode=all](http://search.cpan.org/search?query=redis&mode=all)
, there are a few things right in the search results. We have version numbers,
release dates, and a review score. All of those give you a chance at finding a
half decent library. The first result was updated a week or 2 ago and has 4
significant digits in the version number. None of it's a guarantee but it's a
place to get started.

~~~
rartichoke
It doesn't seem to be a place to get started for Go though. I just did a
search for "golang redis" and it showed me a single perl redis lib?

I like the idea of the reviews and ratings though. Normally I would put almost
no value in a rating system but we need to somehow separate the good from the
bad without having to dive in and look at and profile code from 20 diff libs
on a daily basis.

~~~
iand
CPAN is the repository for Perl modules, not Go

------
cjh_
This font renders odd in IceWeasel 10.0.12 , all occurrences of the letter 'e'
have their left side 'cut off' so they stand out and are very difficult to
read.

Chromium Version 22.0.1229.94 Debian 7.0 (161065) works fine.

~~~
Aissen
Same on Mozilla's official Firefox 19 (beta channel). Raising the font size
(Ctrl +) makes the issue go away.

------
Peaker
Except for his bullet about compiler speed, which might be faster than GHC,
all of his bullets apply to GHC Haskell too.

~~~
papsosouid
I write haskell code all day. I spend my day writing it at work (with
occasional HN breaks obviously) and then I go home and write personal projects
in it. I advocate haskell on a semi-regular basis. I certainly fall on the
pro-haskell side of things. But GHC absolutely does not meet all those bullet
points.

Compiler speed is not some minor difference, it is absolutely massive. Build
times of 30 seconds vs 2 seconds, and that is without counting the 10 seconds
of cabal resolving dependencies.

>Go comes with a complete set of documentation available from the command line

GHC does not come with command line docs.

>All Go code is statically compiled so deployment is trivial

GHC links in C libs dynamically, and as far as I can figure there is no way to
get static linking working, so I have to have all the same C libs installed on
my production servers as my build server. With go you can just upload your
binary to a bare bones server and it works.

>but it also has a tool to clean up code: gofmt

GHC has nothing like this.

>And there's also go fix which can automatically convert Go code designed for
earlier versions to newer versions

Or this.

Haskell is a great language, but it does not match go's toolchain.

~~~
Peaker
> Compiler speed is not some minor difference, it is absolutely massive. Build
> times of 30 seconds vs 2 seconds, and that is without counting the 10
> seconds of cabal resolving dependencies

I simply did not play with Go to know the compilation speeds. I believe you
that it is a massive difference, and it is indeed a major Go advantage.

> GHC does not come with command line docs.

The haddocks are available from the command line. So I don't know what this
means. Hoogle is available from the command line.

> GHC links in C libs dynamically

Ah, I see. Did you try -optl-static? I haven't, but it might work.

> GHC has nothing like this.

There are tools to format Haskell code by certain conventions on hackage.

~~~
tikhonj
This is a complete aside, but what are the good tools for formatting Haskell
code? I've been using stylish-haskell, but it's somewhat limited and barfs on
certain Unicode identifiers I like to use. (I should probably file a bug
report for that...)

~~~
Peaker
Don't know anything better than stylish-haskell, but AFAIK it fits the bullet
point completely.

------
arlasbane
You can always search "go programming", and the search engine should give you
the results of go that occur in the context of programming, which should
usually pertain to the go programming language.

------
drivebyacct2
Go also offers a set of features in the build system that make it obvious and
intuitive to write assembly for different targets, all without having to muck
with makefiles or macros.

<http://golang.org/pkg/go/build/>

