Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions docs/Zero-Assembly-Intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ The Zero compiler project assembly language support.

EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI

### Directives
### Data Directives

* `db <byte>[, ...]` (supports decimal or 0x..)
* `dw <word>[, ...]`
* `dd <dword>[, ...]`
Data Directives are used to allocate data of varying widths.

| Directive | Full Name | Size in Bytes | Use Case | Sample |
|-|-|-|-|-|
| `db` | Define Byte | 1 byte (8-bit) | Characters, strings, etc. | `db <byte>[, ...]` (supports decimal or 0x..)
| `dw` | Define Word | 2 | 16-bit integers, memory offsets, Unicode/UTF-16 characters | `dw <word>[, ...]` |
| `dd` | Define Double Word | 4 | 32-bit integers, single-precision floats, memory addresses | `dd <dword>[, ...]` |
| `dq` | Define Quad Word | 8 | 64-bit pointers, 64-bit integers, double-precision floats | `` |

## Other

Expand Down
67 changes: 64 additions & 3 deletions docs/designs/ZSRC-v0.3-POC-Console.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

In the next generation of Zero, we are re-aligning with the original design specifications and proof-of-concept.

## Zero Source (ZSRC)

The proof-of-concept of the early passes of the Zero language. In its early form, it has a resemblance to C and C#, where it aims to not use pointers

Provides the ability to define the platform and target architecture

```csharp
// Zero v0.2.0-pre
// Demonstrates high-level syntax

// Compiler options
option Platform = WinPE; // Specify the target platform
option Arch = x64; // "Architecture" or "Arch" will work
option Platform(WinPE); // Specify the target platform
option Target(x64); // Target or Architecture ("Arch")

// Library header inclusion
using "Windows.zh";
using "Windows.zh"; // '.zh' denotes, Zero Header.

// Main entry point
int main()
Expand All @@ -29,3 +35,58 @@ int main()

return 0;
}
```

## Zero Assembly (ZASM)

### Raw

Ideal for copy/pasting in from other assemblers.

```csharp
section .data
greeting db 'Hi!', 0x0A ; 'H', 'i', '!', and a newline character (4 bytes)

section .text
global _start

_start:
mov rax, 1 ; sys_write system call
mov rdi, 1 ; file descriptor 1 (stdout)
mov rsi, greeting ; pass the pointer to our DB string
mov rdx, 4 ; the explicit length of our string
syscall ; execute

mov rax, 60 ; sys_exit system call
xor rdi, rdi ; return code 0
syscall
```

### Zero's C-Like Assembly

Zero's C-Like assemblly syntax is intended to catch line errors and accidental section misplacements by use of curley braces `{ }` and semicolons `;`.

```csharp
section .data
{
greeting db 'Hi!', 0x0A; // 'H', 'i', '!', and a newline character (4 bytes)
}

section .text
{
global _start
}

_start:
{
mov rax, 1; // sys_write system call
mov rdi, 1; // file descriptor 1 (stdout)
mov rsi, greeting; // pass the pointer to our DB string
mov rdx, 4; // the explicit length of our string
syscall; // execute

mov rax, 60; // sys_exit system call
xor rdi, rdi; // return code 0
syscall;
}
```
2 changes: 1 addition & 1 deletion docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ When compiling a single `.zsrc` file, the code can use compiler directives in th

* zsrc - source code
* zasm - assembly source code
* zinc - Include / header file
* zinc - Include / header file (zinc, zh)
* zprj - Multi-file zero project (_coming soon_)

## Sample Zero Assembly
Expand Down
112 changes: 112 additions & 0 deletions docs/tutorial-zasm-concat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Joining strings in Zero Assembly

[hello-concat.zasm](../samples/hello-concat.zasm) prints two pieces of text, then
joins them with a space. Joining strings is called **concatenation**.

## 1. Import helper functions

```asm
#IMPORT msvcrt.dll, puts, strcpy, strcat, exit
```

This loads functions from a Windows library:

| Function | Job |
| --- | --- |
| `puts` | Print text and move to the next line. |
| `strcpy` | Copy text into another memory area. |
| `strcat` | Add text to the end of an existing string. |
| `exit` | Finish the program. |

## 2. Make room for the joined text

```asm
sub esp, 64
lea esi, [esp]
```

This reserves 64 bytes on the **stack**, a temporary storage area. `esi` is a
CPU register: a small storage location holding the buffer's address.

The final string needs 21 bytes, including its ending marker.

## 3. Store the words

```asm
call hello_ready
hello_text:
db 72, 101, 108, 108, 111, 0
hello_ready:
pop edi
```

`db` stores bytes. Here, the numbers are ASCII codes spelling `Hello`.
The final `0` marks the end; it is not the character `0`.

`call` jumps over the text and saves its address on the stack. `pop edi` takes
that address into `edi`. The program repeats this trick for `Zero Assembly!`,
storing its address in `ebx`.

## 4. Print each string

```asm
push edi
call [IAT_puts]
add esp, 4
```

`push` supplies the string's address to `puts`. `IAT_puts` points to the imported
function. Afterward, `add esp, 4` removes that argument from the stack.
The program repeats this for the second string.

## 5. Build and print the combined string

The next calls change the buffer in three steps:

```text
strcpy → Hello
strcat → Hello[space]
strcat → Hello Zero Assembly!
```

For these two-argument functions, the source address is pushed first, then the
destination address. `add esp, 8` removes both arguments afterward.

The program prints the buffer with `puts`, then calls `exit` with `0` to signal
success. The joined sentence is built while the program runs.

## Try it

From the repository root, after building the compiler:

```powershell
./zero.exe run samples/hello-concat.zasm
```

Output:

```text
Hello
Zero Assembly!
Hello Zero Assembly!
```

## Reference

A **mnemonic** is a short name for a CPU instruction. This table covers the
instructions and assembler directives used in the sample.

| Mnemonic | Name | What it does | Example from the sample |
| --- | --- | --- | --- |
| `sub` | Subtract | Subtracts a number. Here, moving the stack pointer down reserves 64 bytes of storage. | `sub esp, 64` |
| `lea` | Load effective address | Saves a memory address in a register. It does not read the text stored there. | `lea esi, [esp]` |
| `call` | Call a function or label | Saves the return address on the stack, then jumps to the requested code. | `call hello_ready` |
| `pop` | Take from the stack | Takes the top value off the stack and puts it in a register. | `pop edi` |
| `push` | Place on the stack | Places a value on the stack. This sample uses it to pass function arguments. | `push edi` |
| `add` | Add | Adds a number. Here, moving the stack pointer up removes a used argument. | `add esp, 4` |
| `db` | Define byte | Stores raw bytes in the program, such as ASCII letters and an ending zero. This is an assembler directive. | `db 32, 0` stores a space and its ending zero. |
| `#IMPORT` | Import functions | Declares which functions the program needs from a DLL. This is an assembler directive. | `#IMPORT msvcrt.dll, puts, strcpy, strcat, exit` |

Names ending in `:`, such as `hello_ready:`, are **labels** that name locations
in the program. Names such as `esp`, `esi`, and `edi` are **registers**, not
instructions. `esp` holds the address of the top of the stack.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ source/
Assembly/ Assembler, parsed lines, directives, and import requests
Core/ Shared utility functions
Diagnostics/ Error codes and assembler exceptions
Parsing/ Quote-aware operand and string parsing
Formats/
Pe/ PE writer, layout, imports, and binary structures
Targets/
Expand Down
73 changes: 73 additions & 0 deletions samples/hello-concat.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
; Windows x86 console application: print two strings, then concatenate them.
; From the published folder:
; .\zcc.exe run samples\hello-concat.zasm
; Expected output:
; Hello
; Zero Assembly!
; Hello Zero Assembly!

#IMPORT msvcrt.dll, puts, strcpy, strcat, exit

start:
; Reserve a writable stack buffer. The joined text needs 21 bytes including
; the terminating zero; 64 bytes is sufficient for these fixed strings.
sub esp, 64
lea esi, [esp] ; ESI = destination buffer.

; CALL skips inline data and supplies its address as the return address.
call hello_ready

hello_text:
; Null-terminated ASCII: "Hello".
db 72, 101, 108, 108, 111, 0

hello_ready:
pop edi ; EDI = first string.
call second_ready

second_text:
; Null-terminated ASCII: "Zero Assembly!".
db 90, 101, 114, 111, 32, 65, 115, 115, 101, 109, 98, 108, 121, 33, 0

second_ready:
pop ebx ; EBX = second string.

; puts prints a string and adds a newline.
push edi
call [IAT_puts]
add esp, 4 ; The caller cleans up cdecl arguments.

push ebx
call [IAT_puts]
add esp, 4

; strcpy(buffer, first): initialize the buffer with "Hello" and its zero.
push edi
push esi
call [IAT_strcpy]
add esp, 8

call space_ready
space_text:
db 32, 0 ; Null-terminated ASCII space.

space_ready:
pop eax
; strcat(buffer, " "): replace the old zero with a space and a new zero.
push eax
push esi
call [IAT_strcat]
add esp, 8

; strcat(buffer, second): build "Hello Zero Assembly!" at runtime.
push ebx
push esi
call [IAT_strcat]
add esp, 8

push esi
call [IAT_puts]
add esp, 4

push 0
call [IAT_exit] ; Flush console output and terminate with code 0.
22 changes: 22 additions & 0 deletions samples/hello-db-vars.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
; Windows x86 console application: print a named DB string.
; From the published folder:
; .\zcc.exe run samples\hello-db-vars.zasm
; Expected output: Hello, World!

#IMPORT msvcrt.dll, printf, exit

jmp start ; Skip inline data so the CPU starts with instructions.

message db 'Hello, World!', 0x0A, 0 ; Text, newline (10), and ending zero.
format db '%s', 0 ; Print message as text.

start:
; The name message resolves to the address of the declared bytes.
; printf(format, message) takes arguments pushed right to left.
push message
push format
call [IAT_printf]
add esp, 8 ; Remove both 32-bit arguments from the stack.

push 0
call [IAT_exit] ; Flush console output and exit successfully.
File renamed without changes.
38 changes: 38 additions & 0 deletions samples/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ From the `publish` folder, compile and run a sample:
| Sample | Behavior |
| --- | --- |
| `hello-console.zasm` | Prints `Hello from Zero!` using Windows console output. |
| `hello-concat.zasm` | Prints `Hello` and `Zero Assembly!` on separate lines, then joins them with a space and prints `Hello Zero Assembly!`. |
| `hello-db-vars.zasm` | Declares a named string with `message db 'Hello, World!', 0x0A, 0` and prints it. |
| `v002-hello-msgbox.zasm` | Opens a Windows MessageBox titled `Zero` displaying `Hello Zero!`. Click OK to exit. |
| `v002-integer-math.zasm` | Calculates `7 + 5` and `6 * 7`, then prints the computed results. |

Expand All @@ -29,6 +31,17 @@ above create their executables inside `samples`. To choose another output path:
Omit `run` to compile without executing. Compilation failures prevent execution,
including when an executable from an earlier successful build already exists.

Run the string-concatenation sample with:

```powershell
.\zcc.exe run samples\hello-concat.zasm
```

It uses `strcpy` and `strcat` from Windows' system `msvcrt.dll` to build the final
string in a writable 64-byte stack buffer. `puts` prints each line, and `exit`
flushes output. The joined string is constructed at runtime from the two source
strings and a space; its fixed contents require 21 bytes including the final zero.

The arithmetic sample produces:

```text
Expand All @@ -47,3 +60,28 @@ These applications target Windows x86. The compiler currently writes the console
subsystem for all executables, so the MessageBox sample can also open a console
window when launched from Explorer. Run console samples from an existing terminal
to keep their output visible.

## Named byte declarations

```asm
message db 'Hello, World!', 0x0A, 0
```

`message` names the address of these bytes. `push message` passes that address;
`mov eax, message` or `lea eax, [message]` can also load it. A colon is optional
for byte declarations: `message: db 'Hello, World!', 0x0A, 0` works too.

Quoted strings emit UTF-8 bytes and can use single or double quotes. Commas,
semicolons, and colons inside a string are ordinary text. Double a matching quote
to include it, as in `'It''s Zero'`. Backslashes are literal; use numeric bytes
such as `0x0A` for a newline and `0` for a terminating zero. No ending zero is
added automatically.

Data is currently stored inline with the code in the read-only `.text` section.
When declarations come before instructions, use `jmp start` to skip the data, as
shown in `hello-db-vars.zasm`. These names identify stored bytes; they do not yet
provide writable variables or separate data sections.

```powershell
.\zcc.exe run samples\hello-db-vars.zasm
```
2 changes: 2 additions & 0 deletions source/Zero.Tests/ZAsmTests/AssemblerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class AssemblerTests
{
[TestMethod]
[DataRow("hello-console.zasm", "Hello from Zero!\r\n")]
[DataRow("hello-db-vars.zasm", "Hello, World!\r\n")]
[DataRow("hello-concat.zasm", "Hello\r\nZero Assembly!\r\nHello Zero Assembly!\r\n")]
[DataRow("v002-integer-math.zasm", "7 + 5 = 12\r\n6 * 7 = 42\r\n")]
public void ConsoleSamplePrintsExpectedOutput(string sampleName, string expectedOutput)
{
Expand Down
Loading
Loading