Live data from Hacker News

Introduction to x64 Assembly

software.intel.com

71–78 of 78 posts

Re: Introduction to x64 Assembly

#71
post #19

For those of you that went through Z80, 6502, 68000, x86 macro assemblers like myself, it is just me or does the AT&T syntax just suck? I recently had to convert some code from Intel syntax with NASM macros to GAS with AT&T syntax, and boy what a pain.

I can't stand Intel syntax exactly because it is "backwards" compared to M68k syntax.

Re: Introduction to x64 Assembly

#72
post #66
post #36

Earlier quoted context omitted.

I love this comment. It shows how powerful the right metaphor can be in understanding something, which is something we obsess over at Dev Bootcamp when teaching students. It also shows how tiny affordances ( http://en.wikipedia.org/wiki/Affordance ) make us "think" specific thoughts. I mean, it's called "mov" so something must be moving, which means there must be a subject, object, and possibly an indirect object, ri…

I see this more as a) an example of how well humans can learn to ignore misdirection (the word 'move' hints at src, dest arguments) and b) the first small step towards C: - read "mov X,Y" as "X = Y" - adjust syntax so that it allows "X = Y" (what you see is what you think) - similarly, replace obscure syntax for indexed memory acces by such things as "X = Y[3]" - getting annoyed with the seemingly random limitations…

I wrote my first compiler in M68000 assembler in a similar fashion to your steps. I started by allowing it to recognize M68000 assembler opcodes, and when found it'd just copy the line to output, otherwise it'd parse and compile the line. You could use register names and sizes directly in the statements.

So e.g.

    D0.W = 5
Would translate into:

    MOVE.W #5, D0
I didn't use macros though - handling basic argument passing is simple enough.

As soon as I had the basics of procedures/functions, simple expressions and argument passing in place I started rewriting the compiler using it.

Re: Introduction to x64 Assembly

#73

Earlier quoted context omitted.

"It shows how powerful the right metaphor can be in understanding something" Just like how I was taught the difference between " ". Our teacher drew the rest of Pac-Man around the " " so that we'd think of " " like the mouth of Pac-Man. It wants to eat the larger number. But that was back around 1983 when Pac-Man was all the rage (when I was drawing Pac-Man eating ghosts on my folders).

I learned the same thing in school, but with an Alligator instead of Pac-Man =).

wow. what? what's all this stuff about alligators and pac-men? Isn't the side with two lines just bigger than the pointy side? how do these new entities help? I'm really confused by the small side being the alligator that wants to eat the big side (or did i get that wrong?), let alone the stuff about 4s and 7s!

Re: Introduction to x64 Assembly

#74
post #19

For those of you that went through Z80, 6502, 68000, x86 macro assemblers like myself, it is just me or does the AT&T syntax just suck? I recently had to convert some code from Intel syntax with NASM macros to GAS with AT&T syntax, and boy what a pain.

> For those of you that went through Z80, 6502, 68000, x86 macro assemblers like myself, it is just me or does the AT&T syntax just suck?

My assembly programming background is heavily Intel syntax based, I've done some x86 programming in the 16 bit days and also some Z80 for my TI calculators. So I found the AT&T syntax difficult to read (and write) at first.

But recently I was working on an operating system project and I needed some assembly code. I initially used NASM, then tried GAS/GCC inline asm with .intel_syntax, but I finally settled on AT&T syntax. It was easier to have just one asm syntax in my program (for inline asm in C code and in separate asm files). And it was easier to integrate in my build and toolchain, and no need to install another assembler for my target arch, just gcc+binutils.

So, in the end it was less pain to use AT&T syntax when it comes to tooling. But here's the thing: in less than a week I didn't mind the syntax any more.

So yeah, you might (as I did) think that the AT&T syntax sucks, but sometimes it's easier to use that than to reconfigure tools to use Intel syntax. But just get over it and use the default syntax of your tools. It's not such a big deal.

Re: Introduction to x64 Assembly

#75
post #55

I frequently see recommendations that intrinsics be used instead of assembly. The theory is that they are more portable and just as efficient, which they certainly are on an instruction by instruction level. But I'm not having any luck at writing entire loops with them. All the compilers I've tried (gcc, icc, clang) feel compelled to "optimize" the intrinsics for me, turning my well-tuned and port-conscious loop into…

Put it in a separate translation unit and compile that with different flags.

But seriously, if you're really at the spot where you have real, debugged code that is better than compiler output, the compiler is providing no value and you might as well use the assembly you've written. The point to intrinsics is to expose hardware features that the C language doesn't, not to promise to do it better than the compiler.

Re: Introduction to x64 Assembly

#76
Poor explanations such as this annoy me:

"By replacing the initial R with an E on the first eight registers, it is possible to access the lower 32 bits (EAX for RAX). Similarly, for RAX, RBX, RCX, and RDX, access to the lower 16 bits is possible by removing the initial R (AX for RAX), and the lower byte of the these by switching the X for L (AL for AX), and the higher byte of the low 16 bits using an H (AH for AX)"

It makes learning more difficult. Something like this would be way better:

"Specific parts of the registers can be accessed separately from the rest of the register, within strict limitations dictated by the format of instructions. These register-parts are given easy-to-remember names. The lower 32 bits of the first eight registers can be accessed as EAX, EBX, ECX, EDX, EBP, ESI, EDI and ESP. The lower 16 bits of registers EAX, EBX, ECX and EDX can also be accessed as AX, BX, CX and DX. Finally, both the lower and the second-lower bytes of registers EAX, EBX, ECX, EDX can be separately accessed as AH, AL, BH, BL, CH, CL, DH and DL, with AL/BL/CL/DL being the lowest-order byte and AH/BH/CH/DH being the other one.

Knowing what things are due to what part of the model, and what parts are conventions, is a big part of understanding, which is just building a good model of the architecture in your mind.

It took me years to understand two's complement arithmetic, and the key missing point was that it is just a convention. A convention with great practical advantages, but a convention anyway.

Re: Introduction to x64 Assembly

#77
post #75
post #55

I frequently see recommendations that intrinsics be used instead of assembly. The theory is that they are more portable and just as efficient, which they certainly are on an instruction by instruction level. But I'm not having any luck at writing entire loops with them. All the compilers I've tried (gcc, icc, clang) feel compelled to "optimize" the intrinsics for me, turning my well-tuned and port-conscious loop into…

Put it in a separate translation unit and compile that with different flags. But seriously, if you're really at the spot where you have real , debugged code that is better than compiler output, the compiler is providing no value and you might as well use the assembly you've written. The point to intrinsics is to expose hardware features that the C language doesn't, not to promise to do it better than the compiler.

Put it in a separate translation unit and compile that with different flags.

I've tried it in separate units, and haven't been able to get things out in the order I have them in the source. ICC does the most rearranging (which in most cases other than this leads to faster code), and GCC generally does what you say. But both do things like turning my reloads from memory (to reduce port pressure) into register copies. I was wondering if there were flags I'm not finding to prevent this.

If you're really at the spot where you have real, debugged code that is better than compiler output, the compiler is providing no value and you might as well use the assembly you've written.

Likely the best plan, but this is being used in an open source library where the rest of the work is done with intrinsics. It's a "when in Rome" thing rather than a technical concern.

Re: Introduction to x64 Assembly

#78
post #30
post #19

For those of you that went through Z80, 6502, 68000, x86 macro assemblers like myself, it is just me or does the AT&T syntax just suck? I recently had to convert some code from Intel syntax with NASM macros to GAS with AT&T syntax, and boy what a pain.

Once you get used to AT&T syntax, Intel's seems somewhat verbose. That said, deciphering complex addressing modes (especially for LEAs) in AT&T is pain. So each syntax and its quirks...

I wouldn't call it more verbose.

AT&T:

    sub    $0x8,%rbx
    callq  *%rax
    mov    (%rbx),%rax
Intel:

    sub    rbx, 0x8
    call   rax
    mov    rax, [rbx]
Intel can be written with:

    mov    rax, QWORD PTR [rbx]
But it's redundant and assemblers don't expect it. It's only necessary in a handful of places to avoid ambiguity, as opposed to the incessant size suffixes and $/% prefixes, which make AT&T feel more verbose to me. Definitely a matter of familiarity, though.
Post reply on HN