271 lines
4.7 KiB
NASM
271 lines
4.7 KiB
NASM
|
|
section .text
|
|
|
|
|
|
|
|
initialize_video_mode:
|
|
|
|
.prolog:
|
|
push ax
|
|
|
|
; set the video mode correctly
|
|
xor ah, ah ; bios-function (set video mode)
|
|
mov al, 3 ; video mode with 80x25 characters
|
|
int 0x10
|
|
|
|
.epilog:
|
|
pop ax
|
|
ret
|
|
|
|
; cx: len_buffer
|
|
; si: buffer
|
|
; dl: start_x NOTE: Will contain the end of the text on-screen
|
|
; dh: start_y NOTE: Will contain the end of the text on-screen
|
|
print_string:
|
|
|
|
.prolog:
|
|
push di
|
|
push cx
|
|
push bx
|
|
push ax
|
|
|
|
xor di, di ; character index
|
|
|
|
.printing_loop:
|
|
|
|
.set_cursor_position:
|
|
|
|
mov ah, 0x02
|
|
mov bh, 0
|
|
int 0x10
|
|
|
|
.write_character:
|
|
|
|
push cx ; save len_buffer
|
|
|
|
; get the current character
|
|
mov bx, si
|
|
add bx, di
|
|
mov al, [bx]
|
|
; al now contains the current character
|
|
|
|
; set the other needed interrupt values
|
|
mov ah, 0x0a ; wanted function (write character at cursor position)
|
|
mov bh, 0 ; page number
|
|
mov cx, 1 ; repetitions of character
|
|
int 0x10 ; call bios basic draw functions
|
|
|
|
pop cx ; restore len_buffer
|
|
|
|
|
|
|
|
inc dl ; go to next column
|
|
|
|
; go to a new line if needed
|
|
cmp dl, 80
|
|
jb .no_new_line_needed
|
|
xor dl, dl
|
|
inc dh ; increase column
|
|
|
|
.no_new_line_needed:
|
|
|
|
inc di ; go to next character
|
|
|
|
; go further if the string-printing hasn't been finished
|
|
cmp di, cx
|
|
jb .printing_loop
|
|
|
|
.epilog:
|
|
pop ax
|
|
pop bx
|
|
pop cx
|
|
pop di
|
|
|
|
ret
|
|
|
|
|
|
|
|
; ds: source
|
|
; es: destination
|
|
; dx: len_to_copy
|
|
mem_copy:
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
xor cx, cx
|
|
mov di, dx
|
|
|
|
; ax: first region's value
|
|
; bx: address at index
|
|
; cx: byte_index
|
|
; dx: second region's value
|
|
.loop:
|
|
|
|
; retrieve the source byte at the current index
|
|
mov bx, cx
|
|
mov dx, [bx]
|
|
|
|
; swap the two segments
|
|
; here, ax and bx are used differently.
|
|
mov ax, es
|
|
mov bx, ds
|
|
mov ds, ax
|
|
mov es, bx
|
|
|
|
mov [bx], cx
|
|
|
|
; swap the two segments back
|
|
mov ax, es
|
|
mov bx, ds
|
|
mov ds, ax
|
|
mov es, bx
|
|
|
|
inc cx
|
|
|
|
; if the end has NOT been reached
|
|
cmp cx, di
|
|
jb .loop ; => continue
|
|
|
|
ret
|
|
|
|
|
|
|
|
; ds: region_1
|
|
; es: region_2
|
|
; dx: len_regions
|
|
; ax: result
|
|
mem_equals:
|
|
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push di
|
|
xor cx, cx
|
|
mov di, dx
|
|
|
|
; ax: first region's value
|
|
; bx: address at index
|
|
; cx: byte_index
|
|
; dx: second region's value
|
|
.loop:
|
|
mov bx, cx
|
|
mov dx, [bx]
|
|
|
|
; swap the two segments
|
|
; here, ax and bx are used differently.
|
|
mov ax, es
|
|
mov bx, ds
|
|
mov ds, ax
|
|
mov es, bx
|
|
|
|
mov bx, cx
|
|
mov ax, [bx]
|
|
|
|
cmp ax, dx
|
|
|
|
; swap the two segments back
|
|
mov ax, es
|
|
mov bx, ds
|
|
mov ds, ax
|
|
mov es, bx
|
|
|
|
; jump accordingly to the comparison above
|
|
jne .not_equal
|
|
inc cx
|
|
|
|
cmp cx, di ; if the loop needs to continue
|
|
jb .loop ; (if the end is NOT reached yet)
|
|
|
|
; it goes here if the two regions are completely equal
|
|
pop di
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
|
|
mov ax, 1
|
|
ret
|
|
|
|
.not_equal:
|
|
|
|
pop di
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
|
|
mov ax, 0
|
|
ret
|
|
|
|
|
|
|
|
; ax: start_sector (upper)
|
|
; bl: start_sector (lower)
|
|
; cx: wanted_sector_count
|
|
; dh: drive
|
|
; si: buffer_address (upper)
|
|
; di: buffer_address (lower)
|
|
load_sectors:
|
|
|
|
; INNER WORKING:
|
|
;
|
|
; This function first checks if it needs to load sectors going over
|
|
; a cylinder boundary and loads to that cylinder boundary first continuing
|
|
; in 63-sector - parts after that until the last, < 63-sectors part is read.
|
|
;
|
|
; This is done because some systems don't like reading over the boundaries
|
|
; between the cylinders.
|
|
;
|
|
; The actual part loading the data is in .read_from_disk, it's no different
|
|
; from the first read to the other reads. It just gets different arguments
|
|
; from 1).load_first_sectors, and 2) .load_further_sectors
|
|
;
|
|
|
|
.prolog:
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push si
|
|
xor si, si ; current sector index
|
|
|
|
.load_first_sectors:
|
|
|
|
|
|
|
|
|
|
|
|
; ah: EMPTY
|
|
; al: num_sectors_to_read
|
|
; bx: EMPTY
|
|
; ch: cylinder
|
|
; cl: sector
|
|
; dh: head
|
|
; dl: drive
|
|
.read_from_disk:
|
|
|
|
; set es:bx to the address in bytes to which the output should be written.
|
|
|
|
mov bx, si
|
|
shr bx, 9
|
|
|
|
|
|
|
|
|
|
mov ah, 0x02
|
|
int 0x13
|
|
|
|
|
|
|
|
.load_further_sectors:
|
|
|
|
|
|
|
|
|
|
|
|
.epilog:
|
|
|
|
|
|
|
|
|
|
|