...
This commit is contained in:
@@ -14,12 +14,14 @@
|
||||
<ProjectReference Include="..\Syntax\Syntax.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Runtime\entry.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_memcpy.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_memset.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_mem.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_panic.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_strcmp.s" />
|
||||
<EmbeddedResource Include="Runtime\nub_string.s" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,63 +1,61 @@
|
||||
.intel_syntax noprefix
|
||||
.extern main
|
||||
.section .text
|
||||
|
||||
.global _start
|
||||
.equ SYS_EXIT, 60
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
# On entry, the stack contains:
|
||||
# [rsp] = argc (argument count)
|
||||
# [rsp+8] = argv[0] (program name)
|
||||
# [rsp+16] = argv[1] (first argument)
|
||||
# ...
|
||||
|
||||
# Get argc from stack
|
||||
mov rdi, [rsp] # rdi = argc
|
||||
|
||||
# Calculate space needed for our array structure
|
||||
# We need: 8 bytes (length) + argc * 8 bytes (pointers)
|
||||
mov rax, rdi # rax = argc
|
||||
shl rax, 3 # rax = argc * 8 (each pointer is 8 bytes)
|
||||
add rax, 8 # rax = 8 + argc * 8 (add space for length)
|
||||
# Calculate the size of the array
|
||||
mov rax, rdi # Start with argc
|
||||
shl rax, 3 # Multiply argc by 8
|
||||
add rax, 8 # Add space for the array size
|
||||
|
||||
# Allocate space on stack (align to 16 bytes)
|
||||
add rax, 15 # Round up to nearest 16
|
||||
and rax, -16 # Align to 16 bytes
|
||||
sub rsp, rax # Allocate space
|
||||
# Allocate array size on the stack (aligned to 16 bytes)
|
||||
add rax, 15
|
||||
and rax, -16
|
||||
sub rsp, rax
|
||||
|
||||
# Store array length at beginning
|
||||
mov [rsp], rdi # Store argc as array length
|
||||
# Store number of elements at the start of the array
|
||||
mov [rsp], rdi
|
||||
|
||||
# Copy argv pointers to our array
|
||||
lea rsi, [rsp + 8] # rsi points to start of argv in stack
|
||||
lea rdi, [rsp + 8] # rdi points to our array data (after length)
|
||||
mov rcx, [rsp] # rcx = argc (loop counter)
|
||||
mov rcx, rdi # rcx = loop counter
|
||||
lea rsi, [rsp + rax + 8] # rsi = argv[0]
|
||||
lea rdi, [rsp + 8] # rdi = destination_array[0]
|
||||
|
||||
copy_loop:
|
||||
test rcx, rcx # Check if we're done
|
||||
jz done_copying
|
||||
convert_loop:
|
||||
test rcx, rcx
|
||||
jz done_converting
|
||||
|
||||
mov rax, [rsi] # Load argv[i] pointer
|
||||
mov [rdi], rax # Store in our array
|
||||
# Convert current cstring using nub_cstring_to_string
|
||||
push rcx # Save loop counter
|
||||
push rsi # Save argv[i]
|
||||
push rdi # Save destination_array[i]
|
||||
|
||||
mov rdi, [rsi] # Load current argv[i] (cstring)
|
||||
call nub_cstring_to_string
|
||||
|
||||
pop rdi # Restore destination pointer
|
||||
pop rsi # Restore argv pointer
|
||||
pop rcx # Restore loop counter
|
||||
|
||||
test rax, rax
|
||||
jz conversion_failed
|
||||
|
||||
# Store converted string pointer in our array
|
||||
mov [rdi], rax # Store converted string pointer
|
||||
add rdi, 8 # Move to next destination_array entry
|
||||
add rsi, 8 # Move to next argv entry
|
||||
add rdi, 8 # Move to next array slot
|
||||
dec rcx # Decrement counter
|
||||
jmp copy_loop
|
||||
jmp convert_loop
|
||||
|
||||
done_copying:
|
||||
# Now rsp points to our array: [length][ptr0][ptr1]...[ptrN-1]
|
||||
mov rdi, rsp # Pass array pointer to main
|
||||
done_converting:
|
||||
mov rdi, rsp
|
||||
call main
|
||||
|
||||
# Clean up stack (restore original rsp)
|
||||
# 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
|
||||
mov rdi, rax
|
||||
mov rax, SYS_EXIT
|
||||
syscall
|
||||
|
||||
conversion_failed:
|
||||
call nub_panic
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
.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
|
||||
.global nub_memset
|
||||
nub_memset:
|
||||
push rdi
|
||||
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
|
||||
|
||||
.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
|
||||
array_out_of_bounds:
|
||||
array_oob_msg:
|
||||
.ascii "Index is out of bounds of array\n"
|
||||
|
||||
.section .text
|
||||
.global nub_panic_array_oob
|
||||
nub_panic_array_oob:
|
||||
mov rax, 1 # syscall = sys_write
|
||||
mov rdi, 2 # fd = stderr
|
||||
lea rsi, [rip + array_out_of_bounds] # message
|
||||
mov rdx, 32 # message length
|
||||
.data
|
||||
.align 8
|
||||
oom_msg:
|
||||
.ascii "Out of memory\n"
|
||||
|
||||
.text
|
||||
.globl nub_panic
|
||||
nub_panic:
|
||||
mov rax, SYS_EXIT
|
||||
mov rdi, NUB_PANIC_ERROR_CODE
|
||||
syscall
|
||||
|
||||
mov rax, 60 # sys_exit
|
||||
mov rdi, 101 # exit code
|
||||
.text
|
||||
.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
|
||||
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;
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w ceqw {left}, {right}");
|
||||
@@ -877,13 +871,6 @@ public static class QBEGenerator
|
||||
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))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cnew {left}, {right}");
|
||||
|
||||
Reference in New Issue
Block a user