1

I need to implement scrolling line up using function 06h of interrupt 10h. The problem is that I have the scrolled line, but symbols aren't showing up, cursor disappears and nothing is happening. Maybe I forgot something to consider? To write the code I use FASM. The code is part of a bootloader. Here's piece of code that relates to the scrolling:

cmp cx, 2001
je ScrollLine

I have a counter and when it reaches 2001 (count from 1), control passes to ScrollLine.

ScrollLine:

mov ah, 06h
mov al, 1
mov bh, 07      
mov cx, 0000h
mov dx, 184Fh 
int 10h
ret

My complete bootloader code is as follows:

use16
org 7C00h

start:
    mov ah, 00h  
    mov al, 02h              
    int 10h

    mov ax, NewInt40
    call ChangeIVT

    mov cx, 0

wait_loop:
    xor ax, ax

    inc cx

    cmp cx, 2001
    je ScrollLine

    mov ah, 0
    int 16h

    push ax
    call PrintChar

    jmp wait_loop

NewInt40:   
    sti
    push ax
    mov ax, msg
    cmp bl, 3
    je PrintChar
    cmp bl, 2
    je PrintString
    cmp bl, 1
    je Clear
    cmp bl, 4
    je Scroll
    pop ax
    iret

ChangeIVT:

    push bx
    xor bx, bx

    mov es, bx
    mov bx, 40h
    shl bx, 2

    mov word [es:bx], ax
    mov word [es:bx+2], 0

    pop bx
    ret

PrintString:

    push si
    push bx
    push es
    mov si, ax

    mov ax, 0B800h
    mov es, ax

    xor bx, bx
    xor dx, dx

@@:
    lodsb   

    cmp al, 0
    je @f

    mov byte [es:bx], al
    mov byte [es:bx+1], 1Eh

    mov ah, 0Eh
    add bx, 2
    inc dx
    mov ah,02h
    mov al,02h  
    int 10h
    jmp @b

@@:
    pop es
    pop bx
    pop si
    ret

PrintChar:

    push bp
    mov bp, sp
    push bx
    push es
    push cx

    mov ax, 0B800h
    mov es, ax

    xor bx, bx
    xor dx, dx

    mov ah,3
    int 0x10

    movzx ax, dh
    movzx bx, dl
    mov cx, 80
    push dx
    mul cx
    pop dx
    add bx, ax  ; bx = 80 * dh + dl
    shl bx, 1   ; bx = 2 * (80 * dh + dl)



    mov ax, [bp + 4]
    mov byte [es:bx], al
    mov byte [es:bx+1], 1Eh

    cmp dl, 79
    jl @f

    inc dh
    mov dl, -1
@@:
    inc dl

    pop cx
    mov bh, 0

    mov ah, 2
    int 0x10

    pop es
    pop bx
    mov sp, bp
    pop bp
    ret

Clear:
   mov  AH,0      
   mov  AL,2      
   int  10H       
   ret

Scroll:
    mov ah, 06h
    mov al, 1
    mov bh, 07      
    mov cx, 0000h
    mov dx, 184Fh 
    int 10h
    ret

ScrollLine:
    mov bl, 4
    int 40h
    xor cx, cx
    ret

msg db "Hello, world!", 0Dh, 0Ah, 0

db 510-($-$$) dup (0)

db 55h, 0AAh
Michael Petch
  • 42,023
  • 8
  • 87
  • 158
Fiona P.
  • 35
  • 8
  • So you're making e.g. an 09h afterwards to display a character, and that's when the issue is manifesting? The text scrolls but you subsequently have issues with output? – Tommy Mar 09 '16 at 14:39
  • Can you post some more code? [This](http://pastebin.com/FUKKbSEv) simple demo program (for NASM) use the same interrupt call as yours and works fine. – Margaret Bloom Mar 09 '16 at 14:41
  • @MargaretBloom : bit of a nitpick but in your code what is point of setting up SS:SP, DS, etc when you are creating a COM program (I assume that from org 100h)? DOS loader automatically loads a COM program and sets them all to the same segment and appropriately sets up the stack at the top of the 64k segment. CS=DS=SS all point to the start of the PSP segment. – Michael Petch Mar 09 '16 at 14:52
  • @MichaelPetch. Aww.. bad habits from bootloaders coding. :) – Margaret Bloom Mar 09 '16 at 14:57
  • @Tommy yes. I have a loop that processes keyboard input. `wait_loop: xor ax, ax inc cx cmp cx, 2001 je ScrollLine mov ah, 0 int 16h jmp wait_loop` – Fiona P. Mar 09 '16 at 15:21
  • @MargaretBloom thank you very much, but it didn't help, because your example has no answer to my question. "Scroll up" is working, but the keyboard input isn't processed – Fiona P. Mar 09 '16 at 15:52
  • @P.Fiona It was not meant to answer but to show that there isn't any inherent problem with the call to interrupt *AH=06h/int 10h*. The issue must lie somewhere else in your code. Which we cannot read. :) – Margaret Bloom Mar 09 '16 at 15:59
  • @MargaretBloom I completely agree with you. Please, help me find the error or what is missing. [This](http://pastebin.com/WSHTu4Nh) is my code – Fiona P. Mar 09 '16 at 16:19
  • @P.Fiona : So this code is in a bootloader, not a DOS program? – Michael Petch Mar 09 '16 at 18:55
  • @MichaelPetch yes, this code is future MBR loader. This is just the beginning – Fiona P. Mar 09 '16 at 19:26
  • What is happend if you try to copy the content of the framebuffer for scrollling? Textscreen starts at `0B800:0` in the upper left corner. – Dirk Wolfgang Glomp Mar 09 '16 at 20:02
  • Not related to your problem,but just an observation. Your code would not run on a a 8086/8088/80186/80286 since `movzx` doesn't appear until the 80386. I'm not sure of the requirements for your program, but just wanted point it out. – Michael Petch Mar 09 '16 at 20:37
  • As well not related to your issue (I think Margaret's answer is on the right track), but when you update the interrupt vector table you should do it with interrupts off (use CLI/STI) – Michael Petch Mar 09 '16 at 20:58

1 Answers1

1

You are calling with jumps.

Inside the NewInt40 ISR you conditionally jump to the subroutines PrintString, PrintChar, Scroll, etc. but return from them with a ret.

I don't know how the code is intended to be structured, so I present only the minimal changes necessary to make it works, nothing that could be called a good practice.

Since you are writing a bootloader, you surely know what to fix by now.

NewInt40:   
    sti
    push ax

    push bp             ;; Save caller's BP
    mov bp, sp          ;; Save SP, so we can restore the stack pointer

    push WORD _ni40_end ;; Push return address of every routine

    mov ax, msg
    cmp bl, 3
    je PrintChar
    cmp bl, 2
    je PrintString
    cmp bl, 1
    je Clear
    cmp bl, 4
    je Scroll


_ni40_end:          ;; NASM label
    mov sp, bp      ;; Restore stack pointer (in any case) 
    pop bp          ;; Restore caller BP

    pop ax
    iret

Sorry, I write for NASM, it should be easy to translate to FASM though.

P.S.
When your bootloader "goes crazy", like not responding, or acting on its own, it is likely the symptom that you "lost the flow of execution".
That is intended to mean that you are executing bytes that are not your code and this happen when you return with an unbalanced stack.
If something similar happens again, double check your returns.

Margaret Bloom
  • 33,863
  • 5
  • 53
  • 91
  • He also makes a similar error when he does `je ScrollLine` . Scrollline also does a `ret` – Michael Petch Mar 09 '16 at 21:29
  • One other peculiar issue in his code is `push ax` `call PrintChar` . I don't see him ever cleaning up the stack and removing the parameter after the call is finished. – Michael Petch Mar 09 '16 at 21:48
  • @MichaelPetch I understand all of it, but I need exactly a conditional jump with return back to the program. After all, if I would use `call`, I can't go to the condition. I'm sorry for my english. And thanks for all your comments and corrections – Fiona P. Mar 10 '16 at 17:42
  • @MargaretBloom @MichaelPetch I know that I have made a blunder. But I don't know how can I make `call` on a condition. I know only one way - `cmp` with j(e, ne, a, etc.). And yes, usage of `ret` without `call` is unacceptable. I get it. I'm just a little confused right now – Fiona P. Mar 10 '16 at 18:05
  • 1
    @P.Fiona Margaret has suggested one possible solution. You manually push the return address onto the stack, do the conditional jump and then the `ret` will return to the address pushed on the stack. Alternatively (and maybe simpler for your way of thinking) is to do a conditional jump to a label that in turn does a call to the intended function. – Michael Petch Mar 10 '16 at 18:16
  • @MichaelPetch exactly! Thank you. It's a good remark and a good solution for me. I'll try it – Fiona P. Mar 10 '16 at 18:21