Member Avatar for vs49688
vs49688

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