Live data from Hacker News

Learning to Read X86 Assembly Language

patshaughnessy.net

211–220 of 238 posts

Re: Learning to Read X86 Assembly Language

#211
post #209

Earlier quoted context omitted.

No. This is misleading: fs movs byte [edi], [esi] This is a syntax error: movs byte [fs:edi], [esi] And this is a valid override with sensible syntax: movs byte [edi], [fs:esi]

How would you disassemble that instruction with more than one segment prefix in front of it? The hardware accepts this by ignoring all but the final segment prefix. For example, the prefixes might be: FS, REP, GS, FS, FS Note that code can jump past some of the prefixes. The C library on Linux does this to bypass prefixes. Reasonable assembly syntax needs to be able to describe this. You need to be able to put a labe…

Ideally, like this:

    fs rep gs fs ; Note: extraneous prefix
    mov eax, [fs:ebx]
Some of disassemblers may put them as raw bytes (db 0x63, 0xf3, 0x65, 0x64).

> Note that code can jump past some of the prefixes. The C library on Linux does this to bypass prefixes

What's the use case for this?

I wouldn't split the prefix from the instruction and would rather use label+1 where it's absolutely required.

Re: Learning to Read X86 Assembly Language

#212

Earlier quoted context omitted.

> there are condition flag implications of using XOR and sometimes MOV will be preferable If the condition flags have to be preserved, you are right. But otherwise, read the linked article ( https://randomascii.wordpress.com/2012/12/29/the-surprising-... ): "On Sandybridge this gets even better. The register renamer detects certain instructions (xor reg, reg and sub reg, reg and various others) that always zero a reg…

It's fascinating how far down the rabbit hole goes these days. One might think machine code as emitted by compilers would be pretty close to where the buck stops, but no. Named registers are just an abstraction on top of a larger register pool, opcodes get JIT compiled and optimized to microcode instructions, execution order is mostly just a hint for the processor to ignore if it can get things done faster by reorder…

What I also find rather interesting is the concept of macro-op fusion that Intel introduced with the Core 2 processors: This means for example that a cmp ... (or test ...) followed by a conditional jump can/will be fused together to a single micro-op. In other words: Suddenly a sequence of two instruction maps to one internal micro-op. If you are interested in the details, read section 8.5 in http://www.agner.org/optimize/microarchitecture.pdf

Re: Learning to Read X86 Assembly Language

#213

I thought this sentence was curious: "To write code that runs directly on your microprocessor you need to know how memory segmentation works" Although you can't completely ignore segments, in practice at least on Linux the only segments in use are user code/data and kernel code/data segments. Does anyone know why the author might suggest that understanding segmentation is necessary to write Assembly code?

Probably because you need to deal with the MMU. You can't just write raw assembly and expect it to work (ignoring the MMU), but the kernel takes care of that for you.

I am not following - what is raw assembly? I can write a complete userland program using only Assembly and it will run just fine. When do I need to deal with the MMU exactly?

Re: Learning to Read X86 Assembly Language

#214
post #209

Earlier quoted context omitted.

How would you disassemble that instruction with more than one segment prefix in front of it? The hardware accepts this by ignoring all but the final segment prefix. For example, the prefixes might be: FS, REP, GS, FS, FS Note that code can jump past some of the prefixes. The C library on Linux does this to bypass prefixes. Reasonable assembly syntax needs to be able to describe this. You need to be able to put a labe…

Ideally, like this: fs rep gs fs ; Note: extraneous prefix mov eax, [fs:ebx] Some of disassemblers may put them as raw bytes (db 0x63, 0xf3, 0x65, 0x64). > Note that code can jump past some of the prefixes. The C library on Linux does this to bypass prefixes What's the use case for this? I wouldn't split the prefix from the instruction and would rather use label+1 where it's absolutely required.

An example is bypassing a LOCK prefix when there is only 1 thread or only 1 CPU.

Re: Learning to Read X86 Assembly Language

#215

Earlier quoted context omitted.

Yeah but in most assemblers you're not setting, but either loading or moving values into something, or from somewhere. Because of that, one never has to think in terms of x = y.

What is the difference between "setting" and "loading or moving"? I can't see any semantic difference between "eax = edi" and "mov eax, edi".

None, but in assembler one simply doesn't think in terms of x = y, it's not necessary.

Re: Learning to Read X86 Assembly Language

#216

Earlier quoted context omitted.

This. The AT&T syntax for x86 thing is a huge mistake. All the official docs are Intel syntax. Intel syntax is easier to read and write. Half the gotchas in this article are problems that don't exist in Intel syntax, like the instruction suffixes. The instruction suffixes get even weirder when you get to the sign extending instructions. I wrote an article about this here: http://blog.reverberate.org/2009/07/giving-up…

I prefer Intel syntax and admit that you have a good argument in your article why the AT&T syntax might be problematic, but for newer extensions (SSE etc.) the instruction naming in Intel syntax actually converged towards AT&T syntax: Just to give an example from SSE2 (from http://softpixel.com/~cwright/programming/simd/sse2.php ): paddb - Adds 16 8bit integers. paddw - Adds 8 16bit integers. paddd - Adds 4 32bit int…

That's not really "AT&T syntax", since the suffixes here are denoting how the MMX/XMM register is being split up and not the whole operand size. Those instructions can still be used with either the 64-bit MMX or 128-bit XMM registers:

    paddb mm0, mm1
    paddb xmm0, xmm1
If it was really more like "AT&T" style (I don't know how GNU really does this, so I'm guessing), it would be more like paddqb for MMX and paddob for SSE.

Re: Learning to Read X86 Assembly Language

#217

Also Matt Godbolt's gcc explorer is the the bee's knees for understanding assembly https://godbolt.org/ I think that playing around with it for 2 hours will teach you more than most classes on the topic. It really drives home why interactivity is such a bit deal in education. You should also try writing a script for counting instructions in binaries. It's pretty illuminating. Here are some sample statistics https://w…

One of the most useful tools that helped me learn assembly was the Ketman Assembly Language Tutorial.[1] As I step through an assembly language program, it gives me instant visual feedback of the contents of each register, flag, and memory. I'm really surprised that there's nothing remotely like this on the web yet, and that I have to resort to running dosbox or freedos to have access to this super useful tool. [1] -…

Unfortunately, the tool linked from that page (it's archived) can't be downloaded.

Re: Learning to Read X86 Assembly Language

#218
post #175

Earlier quoted context omitted.

Bear in mind that this isn't a release build, so the generated assembly will not be optimized at all.

There isn't really much more to optimise: at higher optimization levels, the compiler will figure out whether that was a one time operation or not, and if he determines that it was, it will simply hardcode: moveq $52, %eax but all the extra cruft with stack and frame pointer setup will remain unchanged, and will still be there, if only to comply with the ABI calling conventions. I guesstimate that there are up to 50…

-O2 will remove stack pointer setup

Re: Learning to Read X86 Assembly Language

#219
post #217

Earlier quoted context omitted.

One of the most useful tools that helped me learn assembly was the Ketman Assembly Language Tutorial.[1] As I step through an assembly language program, it gives me instant visual feedback of the contents of each register, flag, and memory. I'm really surprised that there's nothing remotely like this on the web yet, and that I have to resort to running dosbox or freedos to have access to this super useful tool. [1] -…

Unfortunately, the tool linked from that page (it's archived) can't be downloaded.

I think you can still find it hosted at other sites by doing a web search for "Ketman Assembly Language Tutorial" or "asmket16.zip".

I also just created a .tar.xz file of my own copy of the tutorial and uploaded it to:

https://www.datafilehost.com/d/6d9086c8

I also did a base64 encoding of the same .tar.xz file and pasted it here:

https://bpaste.net/raw/2521d4e2a230

The sha256 checksum of the .tar.xz file is:

41e5d16b2e0d15f67535d725baa2fa2fec00f65003e4745b60a3fb082111f5ff

Please note that this is not an official version of this tutorial. It's just what I had lying around on my disk after who knows how many years. Use at own risk.

If you want an official copy, you could try contacting the author at btketman@btinternet.com

Re: Learning to Read X86 Assembly Language

#220

Earlier quoted context omitted.

I prefer Intel syntax and admit that you have a good argument in your article why the AT&T syntax might be problematic, but for newer extensions (SSE etc.) the instruction naming in Intel syntax actually converged towards AT&T syntax: Just to give an example from SSE2 (from http://softpixel.com/~cwright/programming/simd/sse2.php ): paddb - Adds 16 8bit integers. paddw - Adds 8 16bit integers. paddd - Adds 4 32bit int…

That's not really "AT&T syntax", since the suffixes here are denoting how the MMX/XMM register is being split up and not the whole operand size. Those instructions can still be used with either the 64-bit MMX or 128-bit XMM registers: paddb mm0, mm1 paddb xmm0, xmm1 If it was really more like "AT&T" style (I don't know how GNU really does this, so I'm guessing), it would be more like paddqb for MMX and paddob for SSE…

I accept the argument that the suffixes mean something a little different in these SSE2 instructions than in the "classical" x86 instructions. But I think it should be clear where these suffixes come from (thus there is some convergence of the Intel syntax for new instruction towards the AT&T syntax). And indeed the instructions paddb, paddw, paddd, paddq are the same on Intel and AT&T syntax. Look at

> https://docs.oracle.com/cd/E19253-01/817-5477/817-5477.pdf

First convince yourself (for example by looking at page 26-39) that in the individual tables the column "Solaris Mnemonic" stands for the AT&T syntax and the column "Intel/AMD Mnemonic" stands for the Intel syntax.

Now look at page 48. Surprise: It is paddb, paddw, paddd, paddq both in Intel and AT&T syntax.

Post reply on HN