I'm trying to write a procedure to write a string directly to the video memory.
It expects the address of the string to be in SI, the length of the string in AH and the offset in video memory to be in AL.
The code correctly handles the length of the string and the offset, but for some reason there is an issue when accessing the memory of the string.
Instead of outputting "Lorem Ipsum", it outputs alternating null characters and the bell character.
It's almost as if the address of the string is not being moved into SI.
Does anyone have any ideas? This is my first ever piece project written in assembly, so I'm new to this.
The full code for the project (a bootloader) is below:
; compile this with "nasm modus.asm -f bin -o modusboot.bin"
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;Origin, tell the assembler that where the code will be in memory after it is been loaded
[section .data]
WelcomeText: db 'Lorem ipsum', 00
[section .text]
; set video mode
mov ax, 3 ; text mode 80x25, 16 colors, 8 pages (ah=0, al=3)
int 10h ; do it!
;cli ; Disable Interrupts. EDIT: No need at this stage
mov si, WelcomeText ; Address of WelcomeText
mov ah, 11 ; Length of WelcomeText
mov al, 5 ; Offset
call memprint16
jmp $ ; Loop-de-loop
memprint16:
; Passed values:
; AH = length of string
; AL = offset of printing
; SI = pointer to string
; Internal:
; CX = position in string (descending)
; BX = temporary storage for the current character
push ax ; Store AX as it needs to be restored later
push bx ; Store BX as it needs to be restored later
push cx ; Store CX as it needs to be restored later
;push ds ; Store DS as it needs to be restored later
add al, al ; multiply the offset by 2 to account for the extra byte
mov cl, ah ; As we're going to be counting downwards (the native direction of CX), put the length of the string into CL
; Set the segment register
mov dx, 0b800h
mov ds, dx
memprint16_printchar:
cmp cx, 0 ; Compare our position in the string to the length of the string.
jz memprint16_ret ; If we are at the end of the string, return
; Otherwise, keep going
; I hate this. We need to get AL into DI, so
mov bx, ax ; Move AX into BX
mov bh, 0 ; Zero BH
mov di, bx ; Move BX (thus BL) into DI
mov bl, [si] ; Get the current character into BL
inc si ; Increment out offset in the string
;Using interrupts
;push ax
;push bx
;mov al, bl
;mov ah, 0Eh
;mov bh, 00h
;mov bl, 07h
;int 10h
;pop bx
;pop ax
;Writing to the video memory
mov byte [di], bl ; Write the character to the video memory
dec cx ; Decrement our current position
add al, 2 ; Increment the video memory offset by 2
jmp memprint16_printchar
memprint16_ret:
;pop ds ; Restore DS
pop cx ; Restore CX
pop bx ; Restore BX
pop ax ; Restore AX
ret ; Return
TIMES 510 - ($ - $$) db 0 ; Fill the rest of sector with 0
DW 0xAA55 ; Add boot signature at the end of bootloader