Live data from Hacker News

The faker's guide to reading x86 assembly language

timdbg.com

21–30 of 49 posts

Re: The faker's guide to reading x86 assembly language

#21
post #6
post #2

Yes, the simple opcodes are the most-used, and this was one of the ideas floating around that helped inspire RISC, but be careful how you figure out which opcodes are different. For example, mov in x86 is extremely polysemous: It can be move from register to register, load register with data from RAM, store register contents out to RAM, store a constant out to RAM, and even perform ALU operations and then use the res…

One thing worth pointing out is that, if you ignore the way the assembly is written and instead look at the binary encoding, then x86 is closer to a RISC idea. Essentially, the core of an x86 instruction is opcode + ModR/M byte, which encodes a register and register-or-memory operand. There's one opcode [1] that means "move from second operand to first operand" and a different opcode that means "move from first opera…

One of my pet ideas is to design a new set of mnemonics and syntax for x64 assembly, the Intel ones are pretty crufty in many ways and imho have potential to be improved. Of course it will not win any popularity contests, but could be interesting design exercise.

Re: The faker's guide to reading x86 assembly language

#22
post #13
post #4

Earlier quoted context omitted.

An easy way to learn to see those patterns is through exploring compiler output: https://godbolt.org/ Other than that, I like "Assembly Language Step By Step" by Jeff Duntemann, which is currently in its third edition and is Linux-only, as opposed to previous editions which were MS-DOS and Linux. He has example assembly code (Intel syntax for NASM, another reason I like his book) for download on his website: http://w…

In my experience the most important parts of reading godbolt output are: 1. Data movements (mov) 2. Control flow (various jumps with corresponding tests, call and ret) 3. Calling convention. But you can often wing this and figure it out from context.

One thing I like for following the control flow is radare2 visual graph modes

Re: The faker's guide to reading x86 assembly language

#23

This was a nice read, but I was hoping for something one step above this. When I was writing an emulator, I spent so much time looking at 8080(ish) code that I began to see constructs for bigger concepts. Like, “oh you’re setting up and running a loop over some subroutine X times.” “You’re checking if a certain math expression equals a certain value before continuing.” Etc. I imagine an Assembly reader sees these thi…

Maybe a decompiler can take you further:

https://boomerang.sourceforge.net/cando.php

https://www.backerstreet.com/decompiler/decompilers.htm

Re: The faker's guide to reading x86 assembly language

#24
post #20
post #7

Earlier quoted context omitted.

Regarding the book, What would be the difference between 32bit and 64bit? Is it still relevant to read today?

Yes - it is one way to do it and it will work and be reasonably efficient. Everyone[1] who knows x86-64 asm today learned 32 bit first. You still have 32 bit instructions, and 16 bit, and 8 bit. The instructions will translate. You get more registers. You need to update the function and syscall calling conventions. There's no reason there can't be "learn x64 asm" books but there aren't many last I looked, but maybe s…

I would doubt that, people haven't been running 32-bit x86 code for years at this point.

Re: The faker's guide to reading x86 assembly language

#25
> But the assembly code will always tell you the truth.

Is this really still the case with modern caching branch-predicting microcode processors? [1]

From what I know (which is little), there is quite a way between assembly and what a processor will actually execute.

[1] just throwing around buzzwords

Re: The faker's guide to reading x86 assembly language

#26

> But the assembly code will always tell you the truth. Is this really still the case with modern caching branch-predicting microcode processors? [1] From what I know (which is little), there is quite a way between assembly and what a processor will actually execute. [1] just throwing around buzzwords

Sure it gets executed using microcode constructed from the assembly. But there's a contract that what happens is precisely what the assembly said, with a little wiggle room for operation order and bus cycle width.

Perhaps it's more correct to say assembler is 'closer to the truth'

Re: The faker's guide to reading x86 assembly language

#27

> But the assembly code will always tell you the truth. Is this really still the case with modern caching branch-predicting microcode processors? [1] From what I know (which is little), there is quite a way between assembly and what a processor will actually execute. [1] just throwing around buzzwords

Just yesterday we had a thread about a core dump that turned out to be a CPU bug (stack pointer being incremented by 1024 in very specific but consistent circumstances), and the discussion had multiple people who encountered kernel or CPU bugs that lead to correct assembly producing incorrect results.

So assembly is evidently not always the truth. It is however the closest we can easily get to the truth (on consumer desktop/server grade processors).

https://news.ycombinator.com/item?id=34230823

Re: The faker's guide to reading x86 assembly language

#28
I dabbed into reverse engineering a while ago (and probably will dive deeper into it seriously later) and realized it is not particularly difficult to recognize constructs in assembly code, but only for simple code such as examples. Once they go up one level, say start using a lot of win32 api, it then makes the business a lot more confusing.

That was why I decided to drop the study temporarily. I wanted to figure out exactly the OS and the type of applications (e.g. DOS virus, or Windows malware) I'd like to reverse engineer for, gain some positive engineering experience and then come back.

Re: The faker's guide to reading x86 assembly language

#29

> But the assembly code will always tell you the truth. Is this really still the case with modern caching branch-predicting microcode processors? [1] From what I know (which is little), there is quite a way between assembly and what a processor will actually execute. [1] just throwing around buzzwords

Less abstract means less is obscured, more truthy.

Higher level languages will have numerous control structures to iterate, consider everything from do-until, do-while, for loops, all the way up to functional languages. That's great. It all gets translated down to machine language code eventually at some low level, either at compile or run time.

Most people iterate in assembly the "simplest" way which will vary by architecture but is generally not overly abstract.

Similar to how its possible to write in an OO style (inheritance, polymorphism, etc) in non-OO languages but most people writing in non-OO languages do not. I think it would be possible to write a bash shell script that implements the concept of polymorphism, but most people would never do that. Its possible and funny to write thousands of lines of code to do "enterprise grade patterns hello world" but most shell scripters will "echo hello world" and call it good which makes it more truthy, less abstract, less obscured.

True, it'll be impossible to infinitely extend and scale the bash "hello world" script, but most software problems are never infinitely extended and scaled anyway. The most powerful tool for a job is rarely the correct tool for the job.

Re: The faker's guide to reading x86 assembly language

#30
post #9

> or calculating pi in roman numerals xxii ----- vii hmmm... now what do i do? how about uppercase/lowercase? XXII ----- = III i iv ii viii ... VII

Love it.

Instead of upper/lower (romans didnt have lowercase?) I would define a latin word, say "dividum" and write it as

CCCXIV DIVIDUM C

Which for short would be:

CCCXIVDVDC

Where DVD is a nonsensical or at least redundant roman numeral (500 + 495 = 995 VM). For readability we now add a new symbol to unicode of a V and a D superimposed.

N.B. Latin nerds... I dont care what the proper term for "divided by" is.

Post reply on HN