Implement a subroutine to print a byte-string of a given length
authorJonas Hvid <mail@johv.dk>
Sat, 7 Mar 2020 16:33:41 +0000 (17:33 +0100)
committerJonas Hvid <mail@johv.dk>
Sat, 7 Mar 2020 16:33:41 +0000 (17:33 +0100)
uefi/main.asm

index aa34ddc9deba4c768e5a3742bc242b3d32c4be12..e038659aa26a533aff600f4d9705f04a741b8692 100644 (file)
@@ -1,6 +1,16 @@
+;; vim: syntax=fasm
+
 format pe64 dll efi
 entry main
 
+;; [TODO] We need to provide the following:
+;; - [X] Print a string of a given length
+;; - [ ] Print a single character
+;; - [ ] Terminate the program (? - What should this do?)
+;; - [ ] Read a single character
+;;       - This should allow the user to type in a string, and then feed the
+;;         buffer to us one character at a time.
+
 ;; #region Structs
 
 ;; Based on https://wiki.osdev.org/Uefi.inc
@@ -46,20 +56,72 @@ main:
   ; At program startup, RDX contains an EFI_SYSTEM_TABLE*.
   mov [system_table], rdx
 
-  mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
-  mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut] ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx
-  mov rdx, hello_world_string
-  ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx, CHAR16* rdx)
-  mov rbx, [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString] ; EFI_TEXT_STIRNG rbx
+  mov rcx, hello_string
+  mov rdx, hello_string.len
+  call print_string
+
+  mov rcx, hello_string
+  mov rdx, hello_string.len
+  call print_string
+
+  mov rcx, hello_string
+  mov rdx, hello_string.len
+  call print_string
+
+  ret
+
+;; Print a string of the given length.
+;;
+;; Inputs:
+;;  - RCX = String buffer
+;;  - RDX = String length
+print_string:
+  mov r8, rcx
+  mov r9, rdx
+
+  mov r10, r9
+  add r10, r10
+
+  ; We take an input string of bytes without any terminator. We need to turn
+  ; this string into a string of words, terminated by a null character.
+  mov rcx, 0
+  mov rsi, 0
+.copy_byte:
+  cmp rcx, r10
+  je .done
+
+  mov al, byte [r8 + rsi]
+  lea rdx, [.output_buffer + rcx]
+  mov byte [rdx], al
+  inc rcx
+  inc rsi
+
+  lea rdx, [.output_buffer + rcx]
+  mov byte [rdx], 0
+  inc rcx
+
+  jmp .copy_byte
+.done:
+  lea rdx, [.output_buffer + r10]
+  mov byte [rdx], 0
+
+  ; At this point we have our null-terminated word-string at .output_buffer. Now
+  ; we just need to print it.
+
+  mov rcx, [system_table]                                       ; EFI_SYSTEM_TABLE* rcx
+  mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]                      ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx
+  mov rdx, .output_buffer
+  mov rbx, [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString] ; EFI_TEXT_STRING rbx
   sub rsp, 32
   call rbx
   add rsp, 32
-
-  mov rax, 0
   ret
 
 section '.data' readable writable
 
 system_table dq ?  ; EFI_SYSTEM_TABLE*
 
-hello_world_string du 'Hello world!', 0xC, 0xA, 0
+hello_string db 'Hello, world!', 0xD, 0xA, 'Here is some more text.', 0xD, 0xA
+.len = $ - hello_string
+
+print_string.output_buffer rq 0x400