Skip to content
This repository was archived by the owner on Jul 17, 2025. It is now read-only.

Commit 8ec364d

Browse files
committed
feat/fix: fix mnemonics bugs and add more mnemonics, add builder, add macros
1 parent 7eba7bd commit 8ec364d

27 files changed

+593
-72
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pip install flexpasm
5454
Once installed, you can start using the library in your Python projects. Check out the [documentation](./docs/en/index.md) for detailed usage examples and API reference.
5555

5656
## Basic Usage
57+
You can view examples in [examples directory](./examples).
5758

5859
### Using templates
5960

@@ -95,6 +96,7 @@ if __name__ == "__main__":
9596

9697
```bash
9798
$ fasm example_templates.asm example_templates
99+
$ ld example_templates -o example_templates
98100
$ ./example_templates
99101

100102
Hello, World!
@@ -192,6 +194,7 @@ if __name__ == "__main__":
192194

193195
```bash
194196
$ fasm example.asm example
197+
$ ld example -o example
195198
$ ./example
196199

197200
Hello, World!

examples/build.asm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2+
;; Author: alexeev-prog ;;
3+
;; Example ASM Program ;;
4+
;; Program generated by FLEXPASM (github.com/alexeev-pro/flexpasm) ;;
5+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6+
7+
format ELF64 executable 3; ; ELF64 EXECUTABLE
8+
entry start ; Set Start Entry
9+
10+
11+
;; Segment readable executable in FASM is a directive for defining a section of code with readable and executable attributes.
12+
segment readable executable
13+
14+
start: ; Label start with 8 commands
15+
MOV RAX, 4 ; Loading 4 value into RAX register.
16+
MOV RCX, message ; Loading message value into RCX register.
17+
MOV RDX, message_size ; Loading message_size value into RDX register.
18+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
19+
MOV RAX, 1 ; Loading 1 value into RAX register.
20+
MOV RBX, RBX ; Exclusive OR operation RBX and RBX using XOR
21+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
22+
JMP exit ; Unconditional jump to label exit
23+
24+
exit: ; Label exit with 3 commands
25+
; Exit with code -1
26+
MOV RAX, 1 ; Loading 1 value into RAX register.
27+
MOV RBX, -1 ; Loading -1 value into RBX register.
28+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
29+
30+
31+
;; Segment readable writeable in FASM is a definition of a segment of program data codes, where the attributes readable (the contents of the segment can be read) and writeable (program commands can both read codes and change their values) are specified for it.
32+
segment readable writeable
33+
34+
message db 'Hello, World!', 0xA ; Var message (string)
35+
message_size = $-message ; Var message (string) length

examples/build.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from flexpasm import ASMProgram
2+
from flexpasm.builder import ASMBuilder, Compiler, File, FileChain, Linker
3+
from flexpasm.constants import LinuxInterrupts
4+
from flexpasm.instructions.registers import get_registers
5+
from flexpasm.instructions.segments import Label
6+
from flexpasm.mnemonics import IntMnemonic, JmpMnemonic, MovMnemonic, XorMnemonic
7+
from flexpasm.settings import Settings
8+
from flexpasm.templates import ExitTemplate
9+
10+
compiler = Compiler()
11+
linker = Linker()
12+
file = File(source_file="build.asm", binary_file="build", object_file="build")
13+
filechain = FileChain(skip_linker=True, compiler=compiler, linker=linker, files=[file])
14+
asmbuilder = ASMBuilder(filechain)
15+
16+
17+
def main():
18+
settings = Settings(
19+
title="Example ASM Program",
20+
author="alexeev-prog",
21+
filename="build.asm",
22+
mode="64",
23+
)
24+
asmprogram = ASMProgram(settings, __name__)
25+
regs = get_registers(settings.mode)
26+
27+
et = ExitTemplate(entry="exit", exit_code=-1)
28+
29+
start_lbl = Label("start")
30+
31+
start_lbl.add_instruction(MovMnemonic(regs.AX, 4))
32+
start_lbl.add_instruction(MovMnemonic(regs.CX, "message"))
33+
start_lbl.add_instruction(MovMnemonic(regs.DX, "message_size"))
34+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
35+
start_lbl.add_instruction(MovMnemonic(regs.AX, 1))
36+
start_lbl.add_instruction(XorMnemonic(regs.BX, regs.BX))
37+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
38+
start_lbl.add_instruction(JmpMnemonic(et.get_label(settings.mode)))
39+
40+
asmprogram.add_label(start_lbl)
41+
asmprogram.add_template(et)
42+
asmprogram.main_rws.add_string("message", "Hello, World!")
43+
44+
asmprogram.save_code()
45+
46+
asmbuilder.run_build()
47+
48+
49+
if __name__ == "__main__":
50+
main()

examples/example.asm

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,32 @@
44
;; Program generated by FLEXPASM (github.com/alexeev-pro/flexpasm) ;;
55
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
66

7-
format ELF64 executable 3; ; ELF64 EXECUTABLE
7+
format ELF64 executable; ; ELF64 EXECUTABLE
88
entry start ; Set Start Entry
99

1010

1111
;; Segment readable executable in FASM is a directive for defining a section of code with readable and executable attributes.
1212
segment readable executable
1313

14-
start: ; Label start with 7 commands
14+
start: ; Label start with 8 commands
1515
MOV RAX, 4 ; Loading 4 value into RAX register.
1616
MOV RCX, message ; Loading message value into RCX register.
1717
MOV RDX, message_size ; Loading message_size value into RDX register.
18-
INT 128 ; Call software interrupt 128: SYSCALL
18+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
1919
MOV RAX, 1 ; Loading 1 value into RAX register.
20-
MOV RBX, RBX ; Exclusive OR operation RBX and RBX using XOR
21-
INT 128 ; Call software interrupt 128: SYSCALL
20+
XOR RBX, RBX ; Exclusive OR operation RBX and RBX using XOR
21+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
22+
JMP exit ; Unconditional jump to label exit
23+
24+
exit: ; Label exit with 3 commands
25+
; Exit with code -1
26+
MOV RAX, 1 ; Loading 1 value into RAX register.
27+
MOV RBX, -1 ; Loading -1 value into RBX register.
28+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
2229

2330

2431
;; Segment readable writeable in FASM is a definition of a segment of program data codes, where the attributes readable (the contents of the segment can be read) and writeable (program commands can both read codes and change their values) are specified for it.
2532
segment readable writeable
2633

27-
message db 'Hello, World!', 0xA ; Var message (string)
34+
message db 'Hello, World!', 0 ; Var message (string)
2835
message_size = $-message ; Var message (string) length

examples/macro.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from flexpasm import ASMProgram
2+
from flexpasm.constants import LinuxInterrupts
3+
from flexpasm.instructions.registers import get_registers
4+
from flexpasm.instructions.segments import Label
5+
from flexpasm.macros import MacroManager
6+
from flexpasm.mnemonics import IntMnemonic, JmpMnemonic, MovMnemonic, XorMnemonic
7+
from flexpasm.settings import Settings
8+
from flexpasm.templates import ExitTemplate
9+
10+
macromanager = MacroManager()
11+
12+
13+
@macromanager.add_macro("test_macro")
14+
def test_macro(regs, start_lbl: Label):
15+
start_lbl.add_instruction(MovMnemonic(regs.AX, 4))
16+
start_lbl.add_instruction(MovMnemonic(regs.CX, "message"))
17+
start_lbl.add_instruction(MovMnemonic(regs.DX, "message_size"))
18+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
19+
start_lbl.add_instruction(MovMnemonic(regs.AX, 1))
20+
start_lbl.add_instruction(XorMnemonic(regs.BX, regs.BX))
21+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
22+
23+
24+
def main():
25+
settings = Settings(
26+
title="Example ASM Program",
27+
author="alexeev-prog",
28+
filename="macros.asm",
29+
mode="64",
30+
)
31+
asmprogram = ASMProgram(settings, __name__)
32+
regs = get_registers(settings.mode)
33+
34+
et = ExitTemplate(entry="exit", exit_code=-1)
35+
36+
start_lbl = Label("start")
37+
38+
macromanager.exec("test_macro", regs=regs, start_lbl=start_lbl)
39+
start_lbl.add_instruction(JmpMnemonic(et.get_label(settings.mode)))
40+
41+
asmprogram.add_label(start_lbl)
42+
asmprogram.add_template(et)
43+
asmprogram.main_rws.add_string("message", "Hello, World!")
44+
45+
asmprogram.save_code()
46+
# asmprogram.restore_backup()
47+
48+
49+
if __name__ == "__main__":
50+
main()

examples/macros.asm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2+
;; Author: alexeev-prog ;;
3+
;; Example ASM Program ;;
4+
;; Program generated by FLEXPASM (github.com/alexeev-pro/flexpasm) ;;
5+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6+
7+
format ELF64 executable; ; ELF64 EXECUTABLE
8+
entry start ; Set Start Entry
9+
10+
11+
;; Segment readable executable in FASM is a directive for defining a section of code with readable and executable attributes.
12+
segment readable executable
13+
14+
start: ; Label start with 8 commands
15+
MOV RAX, 4 ; Loading 4 value into RAX register.
16+
MOV RCX, message ; Loading message value into RCX register.
17+
MOV RDX, message_size ; Loading message_size value into RDX register.
18+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
19+
MOV RAX, 1 ; Loading 1 value into RAX register.
20+
XOR RBX, RBX ; Exclusive OR operation RBX and RBX using XOR
21+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
22+
JMP exit ; Unconditional jump to label exit
23+
24+
exit: ; Label exit with 3 commands
25+
; Exit with code -1
26+
MOV RAX, 1 ; Loading 1 value into RAX register.
27+
MOV RBX, -1 ; Loading -1 value into RBX register.
28+
INT 0x80 ; Call software interrupt 0x80: SYSCALL
29+
30+
31+
;; Segment readable writeable in FASM is a definition of a segment of program data codes, where the attributes readable (the contents of the segment can be read) and writeable (program commands can both read codes and change their values) are specified for it.
32+
segment readable writeable
33+
34+
message db 'Hello, World!', 0 ; Var message (string)
35+
message_size = $-message ; Var message (string) length

examples/simple.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,41 @@
22
from flexpasm.constants import LinuxInterrupts
33
from flexpasm.instructions.registers import get_registers
44
from flexpasm.instructions.segments import Label
5-
from flexpasm.mnemonics import IntMnemonic, MovMnemonic, XorMnemonic
5+
from flexpasm.mnemonics import IntMnemonic, JmpMnemonic, MovMnemonic, XorMnemonic
66
from flexpasm.settings import Settings
7+
from flexpasm.templates import ExitTemplate
78

89

910
def main():
10-
settings = Settings(
11-
title="Example ASM Program",
12-
author="alexeev-prog",
13-
filename="example.asm",
14-
mode="64",
15-
)
16-
asmprogram = ASMProgram(settings, __name__)
17-
regs = get_registers(settings.mode)
11+
settings = Settings(
12+
title="Example ASM Program",
13+
author="alexeev-prog",
14+
filename="example.asm",
15+
mode="64",
16+
)
17+
asmprogram = ASMProgram(settings, __name__)
18+
regs = get_registers(settings.mode)
1819

19-
start_lbl = Label("start")
20+
et = ExitTemplate(entry="exit", exit_code=-1)
2021

21-
start_lbl.add_instruction(MovMnemonic(regs.AX, 4))
22-
start_lbl.add_instruction(MovMnemonic(regs.CX, "message"))
23-
start_lbl.add_instruction(MovMnemonic(regs.DX, "message_size"))
24-
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
25-
start_lbl.add_instruction(MovMnemonic(regs.AX, 1))
26-
start_lbl.add_instruction(XorMnemonic(regs.BX, regs.BX))
27-
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
22+
start_lbl = Label("start")
2823

29-
asmprogram.add_label(start_lbl)
30-
asmprogram.main_rws.add_string("message", "Hello, World!")
24+
start_lbl.add_instruction(MovMnemonic(regs.AX, 4))
25+
start_lbl.add_instruction(MovMnemonic(regs.CX, "message"))
26+
start_lbl.add_instruction(MovMnemonic(regs.DX, "message_size"))
27+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
28+
start_lbl.add_instruction(MovMnemonic(regs.AX, 1))
29+
start_lbl.add_instruction(XorMnemonic(regs.BX, regs.BX))
30+
start_lbl.add_instruction(IntMnemonic(LinuxInterrupts.SYSCALL))
31+
start_lbl.add_instruction(JmpMnemonic(et.get_label(settings.mode)))
3132

32-
asmprogram.save_code()
33-
# asmprogram.restore_backup()
33+
asmprogram.add_label(start_lbl)
34+
asmprogram.add_template(et)
35+
asmprogram.main_rws.add_string("message", "Hello, World!")
36+
37+
asmprogram.save_code()
38+
# asmprogram.restore_backup()
3439

3540

3641
if __name__ == "__main__":
37-
main()
42+
main()

examples/templates.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@
66

77

88
def main():
9-
settings = Settings(
10-
title="Example ASM Program with Templates",
11-
author="alexeev-prog",
12-
filename="example_templates.asm",
13-
mode="32",
14-
)
15-
asmprogram = ASMProgram(settings, __name__)
9+
settings = Settings(
10+
title="Example ASM Program with Templates",
11+
author="alexeev-prog",
12+
filename="example_templates.asm",
13+
mode="32",
14+
)
15+
asmprogram = ASMProgram(settings, __name__)
1616

17-
pst = PrintStringTemplate("Hello, World!")
18-
pst2 = PrintStringTemplate("Hello, World!", "msg2", "print_string2")
19-
start_lbl = Label("start")
17+
pst = PrintStringTemplate("Hello, World!")
18+
pst2 = PrintStringTemplate("Hello, World!", "msg2", "print_string2")
19+
start_lbl = Label("start")
2020

21-
start_lbl.add_instruction(
22-
JmpMnemonic("print_string"), 1, comment="Jump to print strint template"
23-
)
21+
start_lbl.add_instruction(
22+
JmpMnemonic("print_string"), 1, comment="Jump to print strint template"
23+
)
2424

25-
asmprogram.add_label(start_lbl)
26-
asmprogram.add_template(pst)
27-
asmprogram.add_template(pst2)
25+
asmprogram.add_label(start_lbl)
26+
asmprogram.add_template(pst)
27+
asmprogram.add_template(pst2)
2828

29-
asmprogram.save_code()
29+
asmprogram.save_code()
3030

3131

3232
if __name__ == "__main__":
33-
main()
33+
main()

flexpasm/builder/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from flexpasm.builder.builder import ASMBuilder
2+
from flexpasm.builder.toolchain import Compiler, File, FileChain, Linker
3+
4+
all = [Compiler, Linker, File, FileChain, ASMBuilder]

flexpasm/builder/builder.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from flexpasm.builder.toolchain import File, FileChain
2+
from flexpasm.utils import CommandManager
3+
4+
5+
class ASMBuilder:
6+
def __init__(self, filechain: FileChain):
7+
self.filechain = filechain
8+
9+
def add_to_filechain(self, file: File):
10+
self.filechain.files.append(file)
11+
12+
def run_build(self):
13+
compiler = self.filechain.compiler
14+
compiler_flags = "" if compiler.flags is not None else ""
15+
linker = self.filechain.linker
16+
linker_flags = "" if linker.flags is not None else ""
17+
18+
print("Start building\n")
19+
20+
for file in self.filechain.files:
21+
print(f"=== {file.source_file} ===")
22+
23+
compile_command = compiler.compiling_format.format(
24+
flags=compiler_flags,
25+
source_file=file.source_file,
26+
object_file=file.object_file,
27+
)
28+
print(f"Run compile command: {compile_command}")
29+
CommandManager.run_command(compile_command)
30+
31+
if not self.filechain.skip_linker:
32+
link_command = linker.linking_format.format(
33+
flags=linker_flags,
34+
object_file=file.object_file,
35+
binary_file=file.binary_file,
36+
)
37+
print(f"Run link command: {link_command}")
38+
CommandManager.run_command(link_command)
39+
40+
print()
41+
42+
print("End")

0 commit comments

Comments
 (0)