Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- $ *subx*
- ```
- Welcome to SubX, a better way to program in machine code.
- SubX uses a subset of the x86 instruction set. SubX programs will run without modification on Linux computers.
- It provides a better experience and better error messages than programming directly in machine code, but you have to stick to the instructions it supports.
- == Ways to invoke subx
- - Run tests:
- subx test
- - See this message:
- subx --help
- - Convert a textual SubX program into a standard ELF binary that you can run on your computer:
- subx translate <input 'source' file> <output ELF binary>
- - Run a SubX binary using SubX itself (for better error messages):
- subx run <ELF binary>
- To start learning how to write SubX programs, run:
- subx help
- ```
- $ *subx help*
- ```
- help on what?
- Available top-level topics:
- usage
- registers
- syntax
- opcodes
- ```
- $ *subx help registers*
- ```
- SubX currently supports eight 32-bit integer registers: R0 to R7.
- R4 contains the top of the stack.
- There's also a register for the address of the currently executing instruction. It is modified by jumps.
- Various instructions modify one or more of three 1-bit 'flag' registers, as a side-effect:
- - the sign flag (SF): usually set if an arithmetic result is negative, or reset if not.
- - the zero flag (ZF): usually set if a result is zero, or reset if not.
- - the overflow flag (OF): usually set if an arithmetic result overflows.
- The flag bits are read by conditional jumps.
- We don't support non-integer (floating-point) registers yet.
- ```
- $ *subx help syntax*
- ```
- SubX programs consist of segments, each segment in turn consisting of lines.
- Line-endings are significant; each line should contain a single instruction, macro or directive.
- Comments start with the '#' character. It should be at the start of a word (start of line, or following a space).
- Each segment starts with a header line: a '--' delimiter followed by the starting address for the segment.
- The starting address for a segment has some finicky requirements. But just start with a round number, and `subx` will try to guide you to a valid configuration.
- A good rule of thumb is to try to start the first segment at the default address of 0x08048000, and to start each subsequent segment at least 0x1000 (most common page size) bytes after the last.
- If a segment occupies than 0x1000 bytes you'll need to push subsequent segments further down.
- Currently only the first segment contains executable code (because it gets annoying to have to change addresses in later segments every time an earlier one changes length; one of those finicky requirements).
- Check out some examples in this directory (ex*.subx)
- Programming in machine code can be annoying, but let's see if we can make it nice enough to be able to write a compiler in it.
- ```
- $ *subx help opcodes*
- ```
- Opcodes currently supported by SubX:
- 01: add r32 to rm32
- 03: add rm32 to r32
- 05: add imm32 to R0 (EAX)
- 09: rm32 = bitwise OR of r32 with rm32
- 0b: r32 = bitwise OR of r32 with rm32
- 0d: R0 = bitwise OR of imm32 with R0 (EAX)
- 21: rm32 = bitwise AND of r32 with rm32
- 23: r32 = bitwise AND of r32 with rm32
- 25: R0 = bitwise AND of imm32 with R0 (EAX)
- 29: subtract r32 from rm32
- 2b: subtract rm32 from r32
- 2d: subtract imm32 from R0 (EAX)
- 31: rm32 = bitwise XOR of r32 with rm32
- 33: r32 = bitwise XOR of r32 with rm32
- 35: R0 = bitwise XOR of imm32 with R0 (EAX)
- 39: set SF if rm32 < r32
- 3b: set SF if rm32 > r32
- 3d: subtract imm32 from R0 (EAX)
- 50: push R0 (EAX) to stack
- 51: push R1 (ECX) to stack
- 52: push R2 (EDX) to stack
- 53: push R3 (EBX) to stack
- 54: push R4 (ESP) to stack
- 55: push R5 (EBP) to stack
- 56: push R6 (ESI) to stack
- 57: push R7 (EDI) to stack
- 58: pop top of stack to R0 (EAX)
- 59: pop top of stack to R1 (ECX)
- 5a: pop top of stack to R2 (EDX)
- 5b: pop top of stack to R3 (EBX)
- 5c: pop top of stack to R4 (ESP)
- 5d: pop top of stack to R5 (EBP)
- 5e: pop top of stack to R6 (ESI)
- 5f: pop top of stack to R7 (EDI)
- 68: push imm32 to stack
- 74: jump disp8 bytes away if ZF is set
- 75: jump disp8 bytes away if ZF is not set
- 7c: jump disp8 bytes away if lesser (SF != OF)
- 7d: jump disp8 bytes away if greater or equal (SF == OF)
- 7e: jump disp8 bytes away if lesser or equal (ZF is set or SF != OF)
- 7f: jump disp8 bytes away if greater (ZF is unset, SF == OF)
- 81: combine rm32 with imm32 based on subop
- 87: swap the contents of r32 and rm32
- 89: copy r32 to rm32
- 8b: copy rm32 to r32
- 8f: pop top of stack to rm32
- b8: copy imm32 to R0 (EAX)
- b9: copy imm32 to R1 (ECX)
- ba: copy imm32 to R2 (EDX)
- bb: copy imm32 to R3 (EBX)
- bc: copy imm32 to R4 (ESP)
- bd: copy imm32 to R5 (EBP)
- be: copy imm32 to R6 (ESI)
- bf: copy imm32 to R7 (EDI)
- c3: return from most recent unfinished call
- c7: copy imm32 to rm32
- cd: software interrupt (0x80 only)
- e8: call disp32
- e9: jump disp16 bytes away
- eb: jump disp8 bytes away
- f4: halt
- f7: bitwise complement of rm32
- ff: jump/push/call rm32 based on subop
- Coming soon: `subx help operands` for details on words like 'r32' and 'disp8'.
- ```
Add Comment
Please, Sign In to add comment