42 ms·
Introduction to x64 Assembly
- klrr 14y agoThis is awesome, now I have something to do tonight. :-)
- kzrdude 14y agoIntel keeps making up new names for their x86-64 architecture. Now 'x64' did they use that one before? Is IA-32e or EMT64 not better? Also if you want to find out quickly what they mean by 'x64', why is the article tagged with 'ia64' (which means Itanium).
- eliben 14y agox64 has actually been used for quite a while both inside and outside Intel. It's simply a shorter version of x86-64, with all the other alternatives (IA-whatever and EMT<whatever>) never really catching outside Intel.
- tsuraan 14y agoWell, I suppose it wouldn't be expedient for Intel to call it amd64, but of all the nicknames for that arch, I do hate x64 the most. Do people think x86 was a line of 86-bit processors that got slimmed down to make the x64 line?
- anonymfus 14y agoFirst generations of consumer x64 processors were named Athlon 64, so you can read x64 as Athlon 64 compatible if you really want uniformity. x86 also started as unofficial shorthand.
- mbell 14y ago- AMD64 -> Original x86 64bit extension from AMD. - EM64T (EMT64 is a common typo) -> Intel's implementation of AMD64, intel traded SSE3 to AMD for AMD64. - IA-32e -> Same as EM64T, Intel used this name for a bit, mostly during development. - INTEL64 -> Intel renamed EM64T to be more in line with AMD64's naming. - x86-64 -> Overarching instruction set, AMD64 and INTEL64 are implementations. - x64 -> Shorthand for x86-64. x86-64 / x86_64 / x64 are just names for the overarching ISA; AMD64 / INTEL64 are implementations. The AMD64 and INTEL64 implementations aren't actually identical, there are a few differences between them which compilers generally deal with by producing binaries that can handle either implementation. The x86-64 / x86_64 / x64 thing isn't Intel or AMD's fault, it came about because OS vendors used different terms for the arch. Linux for example added support when AMD64 was the only thing around and it wasn't clear what Intel was going to do, they were still pushing Itanium. So the linux kernel used AMD64 as the arch name. Later when Intel licensed AMD64 linux wasn't about to completely rename the arch (and thousands of packages as a result) so now in linux the AMD64 arch strangely supports both AMD64 and INTEL64 targets. On the other hand Apple used x86-64 and x86_64 in the OSX kernel and Sun / Oracle decided to use x64. Really the OS vendors created this mess in combination with awkward timing of support between AMD and Intel.
- maggit 14y agoFrom memory, I seem to remember that the x64 name originally came from Microsoft. They certainly make good use of it, at least, so Sun/Oracle isn't alone :) Just to fill in a (the?) missing piece in an otherwise well assembled puzzle ;)
- asveikau 14y agoI can vouch for the fact, though, that internally the Windows team refers to it as "amd64".
- driax 14y agoRelated is the term x32, which is an architecture (from the point of view of the Linux kernel) for x86-64 code designed to run in 0x86-64 32-bit mode. Why would you do this? Given that you never use 4 GB of memory, you can save a few bytes of memory (32-bit pointers instead of 64-bit) while still getting the extra registers and operations of x86-64 code.
- unwind 14y agoThat 3D "cross" graphic (Figure 1, "General Architecture") might be the worst illustration of a programmer's model for a CPU I've ever seen. I'm sure it makes sense after you've read the accompanying paragraph a sufficient number of times (once didn't cut it, for me), but not so sure it helps in that understanding. I guess it's a funny hint that the x86's architecture is complex, when a figure that's just trying to describe the register names is this complex. :)
- stephencanon 14y agoThe ARMv7 VFP/NEON register layout is just as much fun. Maybe more when you add in the constraints that some instruction need to operate on consecutive registers, and some of them are required to begin on an even-numbered register.
- strags 14y agoI still don't get it. And I've done a bunch of Intel asm. Besides, there are 24 blue boxes and one yellow one. How does this relate to the "16 general purpose 64-bit registers"?
- acqq 14y agoThe pictures with 3 dimension axes have no sense at all. Speaking as somebody who made a reduced set assembly for x64. Did you find something really new or would you just like to confuse more?
- rraawwrr 14y agoI don't think thats the right graphic - a more reasonable graphic is in the PDF which the article is a copy of.
- bcoates 14y agoSomething's going horribly wrong, I'm seeing a screenshot of code to read and parse CPUID.
- niggler 14y agoI learned by working through the software developers' manuals. Many years ago, they used to ship them as physical copies. Nowadays they just send CDs. PDF copies: http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html http://www.intel.com/content/www/us/en/processors/architectu...
- illuminate 14y agoApparently nowadays they refuse to send CDs and demand that you buy them through Lulu.
- niggler 14y agoHmm that must be recent. I have CDs from January 2012
- Locke1689 14y agoWhen did they stop shipping physical copies? I ordered the new manuals for VT-x not 4 years ago and they were happy to ship me the full set of volumes for free.
- niggler 14y agoI tried to order in january 2012 and they said back then that they replaced the free physical books with free CDs. Now it says: Note: We are no longer offering the Intel® 64 and IA-32 Architectures Software Developer’s Manuals on CD-ROM. Hardcopy versions of the manual are available for purchase via a print-on-demand fulfillment model through a third-party vendor, Lulu (please reference 1 and 2 below): http://www.lulu.com/spotlight/IntelSDM http://www.lulu.com/spotlight/IntelSDM.
- nsxwolf 14y agoWhy is there no R8H?
- stephencanon 14y agoThere’s also no R9H ... R15H. These “registers", if they existed, would be bits 8-15 of each of R8, R9, etc. Without talking to engineers at AMD, it’s probably impossible to say precisely why they weren’t provided, but there is generally little/no reason to ever want to use the existing *H registers in 64-bit code, so it’s not surprising that they were omitted. Some combination of low/no demand and added encoding/decode/retirement complexity is an excellent reason to leave things out of an architecture.
- pbsd 14y agoThere are also no RAH, RBH, .... You can only access AH by using the old 32-bit encoding. This happens because in 32-bit x86, you only have access to AL, AH, BL, BH, CL, CH, DL, DH (no lower bytes of EDI, ESP, etc). These are 8 different possibilities, that are encoded by ModR/M's 3 Reg bits. In amd64, they decided to regularize the instruction set: those 3 bits are now used to encode the lower byte of EAX--EDI (AL, CL, ..., DIL). To get R8L, ..., R15L you use the REX.R prefix, which acts as the 4th bit.
- rayiner 14y agoIt's because of the encoding: http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH04/CH04-3.html http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH04/CH04-3.html (Section 4.7). Look at the MOV opcode. In 32-bit code, the opcode byte has one bit that specifies whether the operand size of the instruction is 8 bites or 32 bits (16 bit operands are selected using an operand size prefix). In either case, the MODRM byte has three bits to encode a register number (either the source or destination register depending on a different bit in the opcode byte). That gives you 8 registers to work with. Now the 8086 was not regular. There were 4 GPRs (AX-DX), and 4 pointer registers (SP, BP, SI, DI). It was clear by context whether an instruction would refer to a pointer register or a GPR. But it still had 3 bits for the register number. So these 3 bits were used to treat the 4 16-bit GPRs as 8 8-bit registers. Now, the 386 regularized the architecture to make SP, BP, SI, and DI mostly act as GPRs. But it still has only 3 bits to specify a register number. Intel chose to retain compatibility with the 286, so in 32-bit mode, when the operand size is 8-bits, you can access the lower bytes of EAX-EDX, just like before. But when the operand size is 32-bits, you can access all 8 registers as GPRs. AMD64 comes along and muddies things further. In AMD64, if the REX prefix byte exists, and the instruction has an operand size of 8 bits, then the 16 available register numbers (remember, the REX prefix carries an additional bit for each of the register numbers in MODRM and SIB bytes) address the lower byte of each of the 16 GPRs. However, if the REX prefix is absent, the same model is used as the 386, where the 8 available register numbers address the lower bytes RAX-RDX. And that's why there is no R8H-R15H. Accessing R8-R15 requires the extra bits in the REX prefix, but even with the REX prefix you only have 16 register numbers to work with, and AMD chose to use them to make each GPR accessible as a byte register.
- xhrpost 14y agoIs there a good Windows assembler that doesn't get flagged by anti-virus software? UPDATE: I just ran across JWAsm and haven't encountered any problems so far. http://sourceforge.net/projects/jwasm/ http://sourceforge.net/projects/jwasm/
- xd 14y agohttp://www.nasm.us http://www.nasm.us
- swatkat 14y agoI haven't tried it; but how about Yasm? http://yasm.tortall.net/ http://yasm.tortall.net/ https://github.com/yasm/yasm/ https://github.com/yasm/yasm/
- xhrpost 14y agoThanks. Looks like it requires Visual Studio in Windows. Was hoping to find a simple "ASM" -> "Windows EXE" tool. I might try WinASM again at home.
- jlarocco 14y agoActually, Yasm doesn't require Visual Studio. To create .exe files you'll need a linker, but it works fine with ld.exe from MinGW. Going assembly straight to .exe sounds convenient for learning, but isn't very useful in practice, so not many assemblers implement it. The most common use case for assembly language these days is to write a few functions that get called from some higher level language, and that's done by having both the compiler(s) and assembler spit out object files that are linked together by the linker. I suspect WinASM is just hiding the steps, and it'd be easy enough to create a Makefile that did the same. The closest thing to assembly->exe that I know of is the "flat" binary output from Yasm. It's similar to really old DOS .com executables. I'm not sure they'll run on modern Windows, though.
- xhrpost 14y ago
- pjmlp 14y agoFor 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.
- acallan 14y agoDid you try '.intel_syntax'? I've had some success with it, but it clearly needs some code contributions.
- eliben 14y agoOnce 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...
- 14y ago
- fyolnish 14y ago"Intel stores bytes "little endian," meaning lower significant bytes are stored in lower memory addresses." I would like to meet the person that doesn't know what endianness is, but can still understand that explanation.
- IvyMike 14y agoIt's an okay refresher for those who forget which way is which.
- acallan 14y agoIt's even worse trying to explain Gulliver's Travels (and the origin of Endianness) to engineers that do know it in the data-storage sense.
- jackpirate 14y agoPlease try. I've no idea what you're talking about.
- acallan 14y agoJonathon Swift's "Gulliver's Travels", a satire of 18th century England, included in it a long-running bloody war between two religious sects that started over the correct way to eat a soft-boiled egg: the big end, or the little end. For those not familiar with the history of England, the tome of Western literature (and the genre of satire), or soft-boiled eggs, I've gotten some confused looks when trying to explain this origin. Plus, it doesn't really add anything at all to the understand of endianness in the computer hardware sense.
- easytiger 14y agoSpeaking of which I think this is one of my fav papers to read from an historical computing pov: ON HOLY WARS AND A PLEA FOR PEACE - Danny Cohen 1 April 1980 http://www.ietf.org/rfc/ien/ien137.txt http://www.ietf.org/rfc/ien/ien137.txt
- tptacek 14y ago
- snake_plissken 14y agoI have an older Intel PDF for the EMT64. It makes for some great reading when you want a really deep understanding of how everything works.
- tptacek 14y agox64 is so much nicer than x86 --- ip-relative addressing, more (mercifully, numbered) registers, and (best of all) a register-based calling convention.
- deleted 14y ago[deleted]
- Locke1689 14y agoThe calling convention is a god send. One thing to watch out for people learning IA-32(e) asm is that there are two syntaxes: Intel and AT&T. Intel, unsurprisingly, uses Intel syntax. GCC, however, mostly uses AT&T syntax (for historical reasons, and that's all I'll say). You can find a reference to the GAS syntax at http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax. I wouldn't use it for a reference to any of the instructions (for that grab the linked Intel manuals in this article), but that should get you familiar with the differences if you decide you'd like to write GAS. You do have the option to set GAS to use Intel syntax with a directive, but if you're modifying legacy code or just want to be consistent with a lot of other GAS code, you may want to use AT&T.
- nkurz 14y agoI 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 a hash. For a tight loop of all intrinsics, I can often get a 20% improvement if I use raw assembly in the same written order. Is there any good way to convince these compilers to "do what I said" without turning off all optimizations everywhere?
- ajross 14y agoPut 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.
- nkurz 14y agoPut 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.
- jng 14y agoPoor 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.