Skip to content

Comment on x86 assembly doesn’t have to be scary (2018)parent

Comments

Oh, absolutely:

    LUI  a0, 0x7FFFF
    ADDI a0, a0, 0xFFF
    
is superior to
    MOV eax, 0x7FFFFFFF
Except, of course, that RISC-V snippet doesn't actually load 0x7FFFFFFF into a0 because Reasons, it has to be
    LUI  a0, 0x80000
    ADDI a0, a0, 0xFFF
"But the assembler has the LI pseudoinstruction so it will properly do this calculation for you!". Right, so much for "nice assembly language": you need an actual smart macroassembler to write it.

Talkin' out of my ass here, but is this an artifact of the parameter having to fit in the same instruction word as the opcode ('cause RISC) and because the register is the size of a word (which is partially used by the opcode now), you can't actually load a whole register with an immediate in one go?

Absolutely, and different RISCs coped with it in their own ways. ARM has 12-bit immediates which it treats as having a 8-bit and a 4-bit parts: the 8-bit part is extended into 32 bits and then rotated right twice the number in the 4-bit part. MIPS has 16-bit immediates and the 32-bit load is generally done by LUI then ORI (since MIPS zero-extends the immediates unlike RISC-V which sign-extends those). And RISC-V has 12- (for lower part of the word) and 20-bit (for the upper part) immediates.

The funny part is, there is now the "C" extension to RISC which introduces 16-bit instructions which are allowed to freely mix with 32-bit instructions — so now those 32-bit instructions can be 16-bit aligned and even be split between two physical memory pages which kinda kills the whole "but at least fixed-length encoding prevents Spectre-like exploits" argument.

"But the assembler has the LI pseudoinstruction so it will properly do this calculation for you!". Right, so much for "nice assembly language": you need an actual smart macroassembler to write it.

In x86 the mnemonic "MOV" can be translated into instructions with a different opcode according to the addressing mode, immediate value size, or target register. Most of the x86 instructions have a similar issue, while RISC-V macroassembler are pretty simple. Therefore, the x86 assembler must actually contain much more intelligence than the RISC-V assembler to make it look "simple" and "nice".

Well, sure, it's awkward but also consistent. So once you've learned the rules/pattern for this kind of thing, you can read/write code without having to look up a wack of different instructions and modes and register sets, which x86 is notorious for.

Assembly isn't supposed to be convenient and expressive to write. for that we have high level languages. But some consistency makes for less error prone and easier analysis.

x86 is also consistent, just in a different way. There are basic moves and arithmetics, basic branching, and basic stack-related stuff. Next, there are extensions: string-manipulating extension (STOS/LODS/etc.), multiplication/division extension (MUL/DIV with their idiosyncrastic use of DX:AX), floating-point extension, control-registers extensions (tons of those), vectorized extensions, etc. Inside any set of instructions, things are pretty consistent. It's just that the Intel's Software Developer's Manual is not structured this way, it lumps all of those instructions together.

But RISC-V specification is explicitly structured around describing several basic cores and the extensions to those so it looks like it's all very unified and consistent: and indeed, it mostly is since it was developed mostly in one continuous effort with consistency in mind. Bute there are still some inconsistencies between how things are done in different extensions as well, for example, the "C" extension uses zero-extended immediates in half of its instructions unlike the rest of ISA and the other half of this very extension because of pragmatics: nobody would like to have negative offsets in those shortened instructions, so those are unsigned.

To be clear, that happens simply because ADDI sign-extends its immediate argument. This saves the need for separate immediate opcodes, and is reasonably consistent with the use of sign-extension elsewhere in the ISA.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.