Author: Gary V. Vaughan <firstname.lastname@example.org>
Date: Wed, 16 Nov 2022 17:49:35 -0700
fs/doc/asm/i386.txt: grammar and spelling improvements
|M||fs/doc/asm/i386.txt|| | ||72||+++++++++++++++++++++++++++++++++++++-----------------------------------|
1 file changed, 37 insertions(+), 35 deletions(-)
diff --git a/fs/doc/asm/i386.txt b/fs/doc/asm/i386.txt
@@ -3,18 +3,19 @@
The i386 assembler lives at asm/i386.fs and covers a big part of the
architecture (some parts are not implemented yet).
-You write code by calling operands specifiers followed by an operation word. For
-example, "ax bx add," writes the ADD operations with EAX as a destination and
+You write code by calling operand specifiers followed by an operation word. For
+example, "ax bx add," assembles an ADD operation with EAX as a destination and
EBX as a source.
Register specifiers don't have a "e" prefix and their meaning depend on the
current operation width (see below).
The assembler keeps track of specified operands and will error out with "asm
-error" when operands are nonsensical. For example, "ax add," errors out. "ax bx
-cx" errors out because it's impossible to have more than 2 operands.
+error" when the operands are nonsensical. For example, "ax add," errors out
+because of the missing operand and "ax bx cx" errors out because it's impossible
+to have more than 2 consecutive operands.
-Error checking is not foolproof the the assembler might let you assemble
+But, error checking is not foolproof so the assembler might let you assemble
nonsensical opcodes, for example if you use an addressing mode that is not
supported by the operation you're writing.
@@ -39,7 +40,8 @@ tr6 tr7
If you want to specify a register in a dynamic manner, you can use the uppercase
versions of those registers specified below (which are simple constants that
-yield the encoded in the opcode) and use the "opreg!" word. For example:
+yield the values to be encoded in the opcode) and use the "opreg!" word. For
create mylist DX c, SI c, BP c,
mylist 2 + c@ opreg! inc,
@@ -52,27 +54,27 @@ You can specify an immediate operand with the "i)" word. For example "si 42 i)
sub," writes the SUB operation with ESI as destination and 42 as an immediate
-An immediate operand is always the source so order don't matter, but it's
-usually placed last. You will not get an error by placing it first.
+An immediate operand is always the source so order doesn't matter. It's
+usually placed last, but you will not get an error by placing it first.
## Memory operand
You can refer to a memory address with the "m)" word. "cl $1234 m) mov," loads
-byte at memory address $1234 in register CL.
+the byte at memory address $1234 into register CL.
-Order is important: "$2345 m) dx mov," writes the contents of EDX in memory
+Order is important here: "$2345 m) dx mov," writes the contents of EDX in memory
## Indirect register operand
-We can also refer to memory address stored in register and add a constant offset
-to it. For example, if EDI is $1200, "ax di 42 d) mov," loads the 4 bytes value
-add memory address $122a. Again, order is important and "di 42 d) ax mov" does
+We can also refer to a memory address stored in register with the "d)" word,
+along with a constant offset. For example, if EDI is $1200, "ax di 42 d) mov,"
+loads the 4 byte value from memory address $122a into EAX. Again, order is
+important so "di 42 d) ax mov" does the opposite.
If you want indirect addressing without offset, use "0 d)". The assembler will
-automatically use the operation form that is more compact (because it contains
+automatically use the operation form that is more compact (which contains no
## Operation width
@@ -81,19 +83,18 @@ can be 32-bit, 16-bit or 8-bit wide. There are multiple factors deciding on that
First, using an 8-bit register operator (al, ch, etc.) implicitly switches the
-assembler to 8-bit mode (for one operation, of course).
+assembler to 8-bit mode for just that one operation.
-Some operations can be 8-bit and not involve any register. For example "$1234 m)
-inc,". To have such an operation operate in 8-bit or 16-bit mode, you prefix it
-with "8b!" or "16b!". Example: "8b! $1234 m) inc,". This override lasts one
+But sometimes you want an 8-bit operations that does not involve a register, for
+example "$1234 m) inc,". To force this one operation into 8-bit or 16-bit mode,
+prefix it with "8b!" or "16b!", for example: "8b! $1234 m) inc,".
-You can set the "realmode" global value to 1 to put the assembler in real mode.
-In this mode, the default width is 16-bit until you set "realmode" back to 0.
+You can set the "realmode" global value to 1 to put the assembler in real mode,
+where the default width is 16-bit until you set "realmode" back to 0.
## Jumps and calls
-jmp, and call, have two possible form. Immediate or mod/rm.
+"jmp," and "call," have two possible forms: Immediate or mod/rm.
In mod/rm mode, these operations work like others. For example, "ax jmp," works
as you'd expect.
@@ -105,27 +106,28 @@ offset from the end of the operation). This means that "0 jmp," is always an
At this point a bit of fiddling happens to this offset. First, we check if the
-offset is big enough to fit in 8-bit. If it is, we will write the 8-bit form of
-the jump/call. If it's not, we will write the 32-bit form (or 16-bit form if
-we're in real mode).
+offset is small enough to fit in 8-bits. If it is, we write the 8-bit form of
+the jump/call. If it's not, we write the 32-bit form (or 16-bit form if we're
+in real mode).
-Then, after that, we need to adjust that offset so that it jumps where it's
-supposed to. This means subtracting 2, 3 or 5 bytes to that offset (depending on
-the width) before writing it.
+Then, after that, we need to adjust that offset so that it jumps to where it's
+supposed to by subtracting 2, 3 or 5 bytes (depending on the opcode width)
+before writing it.
Conditional jumps (jz, jnc, etc.) work the same way except that they only
support the immediate mode (again, no "i)") and will subtract an additional 1
-to the resuting offset in 16-bit/32-bit because the opcode is 2 bytes wide.
+from the resulting offset in 16-bit/32-bit because the opcode is 2 bytes wide.
## mul, and div,
-With mul, and div, the destination is always ax and you don't specify it. So,
-you'll write them like "bx mul," or "cx div,"
+With "mul," and "div," the destination is always ax and you don't specify it.
+So, you'll write them like "bx mul," or "cx div,"
## in, and out,
-The in, and out, operations support both their immediate form and their ax/dx
-form. You have to specify registers even if only al and ax are legal. Examples:
+The "in," and "out," operations support both their immediate form and their
+ax/dx form. You have to specify registers even if only al and ax are legal.
42 i) al out, \ 8-bit out to port 42
16b! 42 i) ax in, \ 16-bit in from port 42