...
This commit is contained in:
@@ -14,12 +14,14 @@
|
|||||||
<ProjectReference Include="..\Syntax\Syntax.csproj" />
|
<ProjectReference Include="..\Syntax\Syntax.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Runtime\entry.s" />
|
<EmbeddedResource Include="Runtime\entry.s" />
|
||||||
<EmbeddedResource Include="Runtime\nub_memcpy.s" />
|
<EmbeddedResource Include="Runtime\nub_mem.s" />
|
||||||
<EmbeddedResource Include="Runtime\nub_memset.s" />
|
|
||||||
<EmbeddedResource Include="Runtime\nub_panic.s" />
|
<EmbeddedResource Include="Runtime\nub_panic.s" />
|
||||||
<EmbeddedResource Include="Runtime\nub_strcmp.s" />
|
<EmbeddedResource Include="Runtime\nub_string.s" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,63 +1,61 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
.extern main
|
|
||||||
.section .text
|
|
||||||
|
|
||||||
.global _start
|
.equ SYS_EXIT, 60
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
# On entry, the stack contains:
|
mov rdi, [rsp] # rdi = argc
|
||||||
# [rsp] = argc (argument count)
|
|
||||||
# [rsp+8] = argv[0] (program name)
|
# Calculate the size of the array
|
||||||
# [rsp+16] = argv[1] (first argument)
|
mov rax, rdi # Start with argc
|
||||||
# ...
|
shl rax, 3 # Multiply argc by 8
|
||||||
|
add rax, 8 # Add space for the array size
|
||||||
# Get argc from stack
|
|
||||||
mov rdi, [rsp] # rdi = argc
|
# Allocate array size on the stack (aligned to 16 bytes)
|
||||||
|
add rax, 15
|
||||||
# Calculate space needed for our array structure
|
and rax, -16
|
||||||
# We need: 8 bytes (length) + argc * 8 bytes (pointers)
|
sub rsp, rax
|
||||||
mov rax, rdi # rax = argc
|
|
||||||
shl rax, 3 # rax = argc * 8 (each pointer is 8 bytes)
|
# Store number of elements at the start of the array
|
||||||
add rax, 8 # rax = 8 + argc * 8 (add space for length)
|
mov [rsp], rdi
|
||||||
|
|
||||||
# Allocate space on stack (align to 16 bytes)
|
mov rcx, rdi # rcx = loop counter
|
||||||
add rax, 15 # Round up to nearest 16
|
lea rsi, [rsp + rax + 8] # rsi = argv[0]
|
||||||
and rax, -16 # Align to 16 bytes
|
lea rdi, [rsp + 8] # rdi = destination_array[0]
|
||||||
sub rsp, rax # Allocate space
|
|
||||||
|
convert_loop:
|
||||||
# Store array length at beginning
|
test rcx, rcx
|
||||||
mov [rsp], rdi # Store argc as array length
|
jz done_converting
|
||||||
|
|
||||||
# Copy argv pointers to our array
|
# Convert current cstring using nub_cstring_to_string
|
||||||
lea rsi, [rsp + 8] # rsi points to start of argv in stack
|
push rcx # Save loop counter
|
||||||
lea rdi, [rsp + 8] # rdi points to our array data (after length)
|
push rsi # Save argv[i]
|
||||||
mov rcx, [rsp] # rcx = argc (loop counter)
|
push rdi # Save destination_array[i]
|
||||||
|
|
||||||
copy_loop:
|
mov rdi, [rsi] # Load current argv[i] (cstring)
|
||||||
test rcx, rcx # Check if we're done
|
call nub_cstring_to_string
|
||||||
jz done_copying
|
|
||||||
|
pop rdi # Restore destination pointer
|
||||||
mov rax, [rsi] # Load argv[i] pointer
|
pop rsi # Restore argv pointer
|
||||||
mov [rdi], rax # Store in our array
|
pop rcx # Restore loop counter
|
||||||
add rsi, 8 # Move to next argv entry
|
|
||||||
add rdi, 8 # Move to next array slot
|
test rax, rax
|
||||||
dec rcx # Decrement counter
|
jz conversion_failed
|
||||||
jmp copy_loop
|
|
||||||
|
# Store converted string pointer in our array
|
||||||
done_copying:
|
mov [rdi], rax # Store converted string pointer
|
||||||
# Now rsp points to our array: [length][ptr0][ptr1]...[ptrN-1]
|
add rdi, 8 # Move to next destination_array entry
|
||||||
mov rdi, rsp # Pass array pointer to main
|
add rsi, 8 # Move to next argv entry
|
||||||
|
dec rcx # Decrement counter
|
||||||
|
jmp convert_loop
|
||||||
|
|
||||||
|
done_converting:
|
||||||
|
mov rdi, rsp
|
||||||
call main
|
call main
|
||||||
|
mov rdi, rax
|
||||||
# Clean up stack (restore original rsp)
|
mov rax, SYS_EXIT
|
||||||
# Calculate how much we allocated
|
|
||||||
mov rdi, [rsp] # Get argc back
|
|
||||||
shl rdi, 3 # argc * 8
|
|
||||||
add rdi, 8 # + 8 for length
|
|
||||||
add rdi, 15 # Round up
|
|
||||||
and rdi, -16 # Align
|
|
||||||
add rsp, rdi # Restore stack
|
|
||||||
|
|
||||||
# Exit with main's return value
|
|
||||||
mov rdi, rax # rax contains main's return value
|
|
||||||
mov rax, 60 # sys_exit
|
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
|
conversion_failed:
|
||||||
|
call nub_panic
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
.section .text
|
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_memcpy
|
||||||
|
# func nub_memcpy(destination: ^u8, source: ^u8, count: u64): ^u8
|
||||||
|
nub_memcpy:
|
||||||
|
mov rcx, rdx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_memset
|
||||||
# func nub_memset(destination: ^u8, value: i8, count: u64): ^u8
|
# func nub_memset(destination: ^u8, value: i8, count: u64): ^u8
|
||||||
.global nub_memset
|
|
||||||
nub_memset:
|
nub_memset:
|
||||||
push rdi
|
push rdi
|
||||||
mov rcx, rdx
|
mov rcx, rdx
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
.intel_syntax noprefix
|
|
||||||
.section .text
|
|
||||||
|
|
||||||
# func nub_memcpy(destination: ^u8, source: ^u8, count: u64): ^u8
|
|
||||||
.global nub_memcpy
|
|
||||||
nub_memcpy:
|
|
||||||
push rdi
|
|
||||||
mov rcx, rdx
|
|
||||||
test rcx, rcx
|
|
||||||
jz memcpy_done
|
|
||||||
memcpy_loop:
|
|
||||||
mov al, BYTE PTR [rsi]
|
|
||||||
mov BYTE PTR [rdi], al
|
|
||||||
inc rsi
|
|
||||||
inc rdi
|
|
||||||
dec rcx
|
|
||||||
jnz memcpy_loop
|
|
||||||
memcpy_done:
|
|
||||||
pop rax
|
|
||||||
ret
|
|
||||||
@@ -1,19 +1,47 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
.section .data
|
.equ NUB_PANIC_ERROR_CODE, 101
|
||||||
|
|
||||||
|
.equ SYS_WRITE, 1
|
||||||
|
.equ SYS_EXIT, 60
|
||||||
|
|
||||||
|
.equ FD_STDIN, 0
|
||||||
|
.equ FD_STDOUT, 1
|
||||||
|
.equ FD_STDERR, 2
|
||||||
|
|
||||||
|
.data
|
||||||
.align 8
|
.align 8
|
||||||
array_out_of_bounds:
|
array_oob_msg:
|
||||||
.ascii "Index is out of bounds of array\n"
|
.ascii "Index is out of bounds of array\n"
|
||||||
|
|
||||||
.section .text
|
.data
|
||||||
.global nub_panic_array_oob
|
.align 8
|
||||||
nub_panic_array_oob:
|
oom_msg:
|
||||||
mov rax, 1 # syscall = sys_write
|
.ascii "Out of memory\n"
|
||||||
mov rdi, 2 # fd = stderr
|
|
||||||
lea rsi, [rip + array_out_of_bounds] # message
|
.text
|
||||||
mov rdx, 32 # message length
|
.globl nub_panic
|
||||||
|
nub_panic:
|
||||||
|
mov rax, SYS_EXIT
|
||||||
|
mov rdi, NUB_PANIC_ERROR_CODE
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
mov rax, 60 # sys_exit
|
.text
|
||||||
mov rdi, 101 # exit code
|
.globl nub_panic_array_oob
|
||||||
|
nub_panic_array_oob:
|
||||||
|
mov rax, SYS_WRITE
|
||||||
|
mov rdi, FD_STDERR
|
||||||
|
lea rsi, [rip + array_oob_msg]
|
||||||
|
mov rdx, 32
|
||||||
syscall
|
syscall
|
||||||
|
call nub_panic
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_panic_oom
|
||||||
|
nub_panic_oom:
|
||||||
|
mov rax, SYS_WRITE
|
||||||
|
mov rdi, FD_STDERR
|
||||||
|
lea rsi, [rip + oom_msg]
|
||||||
|
mov rdx, 14
|
||||||
|
syscall
|
||||||
|
call nub_panic
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
.intel_syntax noprefix
|
|
||||||
.section .text
|
|
||||||
|
|
||||||
# func nub_strcmp(lhs: ^u8, rhs: ^u8): bool
|
|
||||||
.global nub_strcmp
|
|
||||||
nub_strcmp:
|
|
||||||
xor rdx, rdx
|
|
||||||
strcmp_loop:
|
|
||||||
mov al, BYTE PTR [rsi + rdx]
|
|
||||||
mov bl, BYTE PTR [rdi + rdx]
|
|
||||||
inc rdx
|
|
||||||
cmp al, bl
|
|
||||||
jne strcmp_not_equal
|
|
||||||
cmp al, 0
|
|
||||||
je strcmp_equal
|
|
||||||
jmp strcmp_loop
|
|
||||||
strcmp_not_equal:
|
|
||||||
mov rax, 0
|
|
||||||
ret
|
|
||||||
strcmp_equal:
|
|
||||||
mov rax, 1
|
|
||||||
ret
|
|
||||||
100
src/CLI/Runtime/nub_string.s
Normal file
100
src/CLI/Runtime/nub_string.s
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.equ SYS_MMAP, 9
|
||||||
|
.equ SYS_MUNMAP, 11
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_strlen
|
||||||
|
# func nub_strlen(string: cstring): u64
|
||||||
|
nub_strlen:
|
||||||
|
test rdi, rdi
|
||||||
|
jz null_string
|
||||||
|
xor rax, rax
|
||||||
|
strlen_loop:
|
||||||
|
cmp byte ptr [rdi + rax], 0
|
||||||
|
je strlen_exit
|
||||||
|
inc rax
|
||||||
|
jmp strlen_loop
|
||||||
|
null_string:
|
||||||
|
xor rax, rax
|
||||||
|
strlen_exit:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_cstring_to_string
|
||||||
|
# func nub_cstring_to_string(string: cstring): []u8
|
||||||
|
nub_cstring_to_string:
|
||||||
|
push rbx
|
||||||
|
push r12
|
||||||
|
push r13
|
||||||
|
|
||||||
|
mov rbx, rdi # Save original pointer
|
||||||
|
call nub_strlen
|
||||||
|
mov r12, rax # r12 = string length
|
||||||
|
|
||||||
|
# Calculate total space needed: 8 bytes (length) + string length
|
||||||
|
mov r13, r12
|
||||||
|
add r13, 8 # r13 = total bytes needed
|
||||||
|
|
||||||
|
# Round up to page size (4096 bytes) for mmap
|
||||||
|
add r13, 4095 # Add page_size - 1
|
||||||
|
and r13, -4096 # Align to page boundary
|
||||||
|
|
||||||
|
mov rax, SYS_MMAP
|
||||||
|
xor rdi, rdi # addr = 0 (let kernel choose)
|
||||||
|
mov rsi, r13 # length = aligned size
|
||||||
|
mov rdx, 3 # prot = PROT_READ | PROT_WRITE
|
||||||
|
mov r10, 34 # flags = MAP_PRIVATE | MAP_ANONYMOUS (0x22)
|
||||||
|
mov r8, -1 # fd = -1
|
||||||
|
xor r9, r9 # offset = 0
|
||||||
|
syscall
|
||||||
|
|
||||||
|
# Check if mmap failed
|
||||||
|
cmp rax, -1
|
||||||
|
je mmap_failed
|
||||||
|
|
||||||
|
mov r13, rax # r13 = pointer to mapped memory
|
||||||
|
|
||||||
|
# Store length at beginning of mapped memory
|
||||||
|
mov [r13], r12 # Store string length
|
||||||
|
|
||||||
|
# Copy string data if not empty
|
||||||
|
test r12, r12 # Check if length is 0
|
||||||
|
jz copy_done
|
||||||
|
|
||||||
|
lea rdi, [r13 + 8]
|
||||||
|
mov rsi, rbx
|
||||||
|
mov rcx, r12
|
||||||
|
call nub_memcpy
|
||||||
|
|
||||||
|
copy_done:
|
||||||
|
mov rax, r13
|
||||||
|
jmp function_exit
|
||||||
|
|
||||||
|
mmap_failed:
|
||||||
|
xor rax, rax
|
||||||
|
|
||||||
|
function_exit:
|
||||||
|
pop r13
|
||||||
|
pop r12
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl nub_string_free
|
||||||
|
# func nub_string_free(string: []u8): void
|
||||||
|
nub_string_free:
|
||||||
|
test rdi, rdi
|
||||||
|
jz free_exit
|
||||||
|
|
||||||
|
mov rsi, [rdi]
|
||||||
|
add rsi, 8
|
||||||
|
|
||||||
|
# Round up to page size
|
||||||
|
add rsi, 4095
|
||||||
|
and rsi, -4096
|
||||||
|
|
||||||
|
mov rax, SYS_MUNMAP
|
||||||
|
syscall
|
||||||
|
free_exit:
|
||||||
|
ret
|
||||||
@@ -849,12 +849,6 @@ public static class QBEGenerator
|
|||||||
return outputName;
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String))
|
|
||||||
// {
|
|
||||||
// _builder.AppendLine($" {outputName} =w call $nub_strcmp(l {left}, l {right})");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" {outputName} =w ceqw {left}, {right}");
|
_builder.AppendLine($" {outputName} =w ceqw {left}, {right}");
|
||||||
@@ -877,13 +871,6 @@ public static class QBEGenerator
|
|||||||
return outputName;
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String))
|
|
||||||
// {
|
|
||||||
// _builder.AppendLine($" {outputName} =w call $nub_strcmp(l {left}, l {right})");
|
|
||||||
// _builder.AppendLine($" {outputName} =w xor {outputName}, 1");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" {outputName} =w cnew {left}, {right}");
|
_builder.AppendLine($" {outputName} =w cnew {left}, {right}");
|
||||||
|
|||||||
Reference in New Issue
Block a user