Reference
2026-07-18 · 4 min read

Modifiers

AI notice: This text is created with the support of AI systems; it is reviewed editorially and taken responsibility for before publication.

The modifier is the suffix after the dot: MOV.I, ADD.AB, SEQ.F. It determines which fields of an instruction are read and written.

It looks inconspicuous. In fact it determines the meaning of an instruction more than the opcode in front of it — two characters regularly decide between a working warrior and a dead one.

The seven modifiers

Every instruction has two fields, A and B. An operation has a source (the A-operand) and a target (the B-operand). The modifier says which field of the source acts on which field of the target:

Modifier Source → target
.A A → A
.B B → B
.AB A → B
.BA B → A
.F A → A and B → B
.X A → B and B → A (crossed)
.I the entire instruction, including opcode and addressing modes

The pairs most often confused are .AB with .BA, and .F with .X. A mnemonic: in .AB and .BA the first letter is the source, the second the target. .F is "flat" (each field stays with its own kind), .X is "crossed".

Verified

This table is not copied but measured. The test sets a source to #1, #2, performs the operation onto an empty target cell and compares the result with the expected value:

Operation Target before Target after confirmed
MOV.A #0, #0 #1, #0
MOV.B #0, #0 #0, #2
MOV.AB #0, #0 #0, #1
MOV.BA #0, #0 #2, #0
MOV.F #0, #0 #1, #2
MOV.X #0, #0 #2, #1

As a control, the same test was repeated with deliberately wrong expected values — there it fails in every round. So the test genuinely discriminates instead of merely agreeing.

.I is a special case

.I transfers the complete instruction: both fields, both addressing modes and the opcode.

That makes it the only modifier capable of moving executable code. All the others move numbers alone and leave the target cell's opcode untouched — so the target cell remains whatever it was, usually a DAT.

How large the difference is shows in the imp. The same warrior, only the modifier changed, 2000 rounds each:

Variant Score
MOV.I $0, $1 74.5
MOV.A, .B, .AB, .BA, .F, .X 0.0 (2000 losses each)

An imp using .F dutifully copies both number fields into the neighbouring cell — but DAT still stands there. It writes its own grave and walks into it on the next cycle.

For arithmetic instructions, .I effectively does not exist. ADD.I behaves like ADD.F — measured. That makes sense, since adding an opcode has no meaning.

Which modifier for what

Situation Usual Why
copying code, bombing with whole instructions .I only modifier that transfers the opcode
moving a pointer by a constant .AB constant sits as # in the A-field, target in the B-field
advancing two pointers at once .F both fields in one go
scanning .I or .F .I more precise, .F quicker to write
range check with SLT .AB limit immediate, tested value in the B-field

When comparing, the difference between .I and .F deserves a thought: .I compares the complete instruction and therefore also detects differences in the opcode. .F compares only the two number fields — two cells with identical numbers but different opcodes count as identical there. For a scanner that can be the difference between a find and a miss.

If you write none

If you omit the modifier, the assembler inserts one — according to fixed rules depending on the opcode and on the mode of the A-operand. The complete table is under Instruction set.

Two places where the default surprises:

  • SLT without # becomes .B, not .F like the other arithmetic instructions.
  • Jump instructions ignore the A-mode entirelyDJN #1, $2 becomes .B even though the A-operand holds an immediate value.

The recommendation stands: always write the modifier yourself. Not because the defaults are wrong, but because they are invisible — and a bug whose cause is not in the source costs more time than typing two characters.


← Core War overview