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 (lower) ; bl: start_sector (upper) ; cx: sector_count ; dh: drive ; es: buffer_address (upper) ; di: buffer_address (lower) load_sectors: .prolog: push ax push bx push cx push dx push si xor si, si ; current sector index ; calculate the distance (in sectors) to the next cylinder boundary ; get the index of the current cylinder and ax, 0b00111111 ; extract only the sector index mov bx, 64 ; get the maximum number of sectors + 1 sub bx, ax ; invert the result; 1 becomes 63; 63 becomes 1 cmp ax, 63 jne .is_not_on_full_cylinder_boundary ; if it's indeed on a full cylinder boundary, the first_read-part is unimportant mov ax, 0 set_load_args .is_not_on_full_cylinder_boundary: ; cx still contains the entry-point's wanted sector_count ; ax now contains the distance to the next cylinder boundary cmp cx, ax jbe .load_data ; it gets here if there are more sectors needed after the ; next cylinder boundary ; if the number of sectors ; which are wanted (sector_count) is above the ; distance to the next cylinder boundary ; if not that many sectors are needed, just read as ; many sectors as are needed in total mov cx, bx jmp .load_data ; sets the arguments for a run of '.load_data' after the ; first one; aligned on a CHS - cylinder boundary .set_load_args: mov bx, sp add bx, 4 mov cx, [bx] sub cx, si ; cx = num_missing_sectors cmp cx, 63 jbe .add_num_missing_sectors_to_sector_index ; if this goes here, there are more than 63 sectors ; still missing to be loaded ; -> clamp them to 63 so they can be loaded. mov cl, 63 jmp .load_data .add_num_missing_sectors_to_sector_index: add si, cx ; loads at most 64 sectors from the disk into the main memory ; ax: scratchpad ; bx: start_sector (high part) ; ch: start_sector (low part) ; cl: num_sectors .load_data: mov ah, 0x02 mov al, cl mov dl, [bx] ; drive mov dh, bh ; head mov cl, ch ; sector mov ch, bl ; cylinder mov bx, di ; buffer address (lower) int 0x13 .continue_if_needed: ; check if there still are sectors missing to load mov bx, sp add bx, 4 mov cx, [bx] ; sector_count cmp si, cx jb .set_load_args .epilog: pop si pop dx pop cx pop bx pop ax ret