Jump to content

Real mode text editor issue

- - - - -

  • Please log in to reply
44 replies to this topic

#1
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Hi, I recently created what I guess you could call a text editor that boots off a floppy. Pretty much, it echos everything you type on to the screen, then when you press Ctrl+S, it saves it to the 2nd sector on the floppy, then goes in to a loop of HLT's. It worked until I added something to make it scroll when it reached the end of the screen, now it just displays the first character that I type, and then gets frozen. Here is the messy code:

mov ax,0xb800

mov gs,ax

mov di,0

mov dx,0x0500

mov fs,dx

mov bp,0

mov sp,0

loop:

call poll


if0:

cmp sp,2000

jne if1

call scroll

sub sp,80

jmp loop


if1:

cmp al,0x08

jne else

cmp di,0

je loop

sub di,2

dec bp

mov byte [fs:bp],0x00

mov byte [gs:di],0x00

dec sp

jmp loop


else:

mov byte [fs:bp],al

inc bp

mov byte [gs:di],al

inc di

mov byte [gs:di],0x07

inc di

inc sp

jmp loop


poll:

mov ah,0

int 0x16

cmp ax,0x1f13

jne continue

jmp write

continue:

ret


write:

mov ah,3

mov al,5

mov ch,0

mov cl,2

mov dh,0

mov dl,0

mov bx,fs

mov es,bx

mov bx,0

int 0x13

jmp halt


scroll:

mov ah,7

mov al,1

mov bh,1

int 0x10

ret


halt:

hlt

jmp halt

Any help would be appreciated :)
Latinamne loqueris?

#2
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Sorry about the double post, but can someone please reply?
Latinamne loqueris?

#3
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I decided to take the approach of using int 10h for output etc. Here is my new code:
mov bl,0x07

xor dx,dx

mov ebp,stackb

mov esp,stacke

mov dx,0x800

mov es,dx


loop:

call poll

mov ah,0x0e

cmp al,0x08

je loopif1

cmp ax,4b00h

je leftarrow

cmp ax,4d00h

je rightarrow

jmp loopelse


leftarrow:

push ax

push bx

push cx

push dx

call deccursor

pop dx

pop cx

pop bx

pop ax

jmp loop


rightarrow:

push ax

push bx

push cx

push dx

call inccursor

pop dx

pop cx

pop bx

pop ax

jmp loop


loopif1:

cmp di,0

je loop

dec dx

mov cx,bx

mov bx,dx

mov byte [es:bx],al

mov bx,cx

mov al,8

int 0x10

mov al,' '

int 0x10

mov al,8

int 0x10

jmp loop


loopelse:

int 0x10

mov cx,bx

mov bx,dx

mov byte [es:bx],al

mov bx,cx

inc dx

jmp loop


poll:

mov ah,0

int 0x16

cmp ax,0x1f13

jne continue

jmp write

continue:

ret


pause:

push ax

mov ah,0

int 0x16

pop ax

ret


write:

mov ah,3

mov al,5

mov ch,0

mov cl,2

mov dh,0

mov dl,0

mov bx,dx

int 0x13

jmp halt


deccursor:

mov ah,3

mov bh,0

int 0x10

cmp dl,0

jne deccelse


deccif2:

mov dl,79

dec dh

mov ah,2

int 10h

ret


deccelse:

dec dl

int 10h

ret


inccursor:

mov ah,3

mov bh,0

int 10h

cmp dl,79

jne inccelse


inccif1:

mov dl,0

inc dh

mov ah,2

int 10h

ret


inccelse:

inc dl

int 10h

ret


halt:

cli

hlt

jmp halt


section .bss

stackb: resb 4096

stacke:
Everything about the program is fine, except that when I press the left arrow, it moves the cursor right, just like pushing the right arrow, and instead of saving to the 2nd sector, it saves at the 5th sector. What did I do wrong?

Edited by mebob, 02 October 2010 - 07:18 PM.
Forgot something

Latinamne loqueris?

#4
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Don't call a label 'loop' (or anything else for that matter), as that's an Intel instruction. I'll take a look at it again later tonight and see if I can find anything else wrong. I doubt that's the actual problem, though.
sudo rm -rf /

#5
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I doubt that's the problem either, because I had it named that before the problems started popping up. And thanks in advance for taking a look.
Latinamne loqueris?

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript

  mov   ah, 0x0e    <---+

  cmp   al, 0x08        |

  je    loopif1         |

  cmp   ax, 4b00h   <---+

  je    leftarrow       |

  cmp   ax, 4d00h   <---+

Are you still using that piece of code? Because that'd trash your values.

A few other problems:
1) deccif2: You never check to see if the row (dh) is already zero; if it is then it'll wrap around to 255 and do who knows what.
2) You can't assume that BX will still hold the page number when the interrupt returns. Or any general register, for that matter. You should reload it after calling an interrupt. See deccelse and inccelse.
3) For our sanity, please come up with better names for your labels, and try not to make them global. (And comment.) For example, instead of this:

deccursor:

  mov ah,3

  mov bh,0

  int 0x10

  cmp dl,0

  jne deccelse


deccif2:

  mov dl,79

  dec dh

  mov ah,2

  int 10h

  ret


deccelse:

  dec dl

  int 10h

  ret

you could have:

cursor_back:

  mov ah, 3         ; get cursor size and position; row in DL, col in DH

  mov bh, 0

  int 0x10

  

  cmp dl, 0         ; check to see if cursor is at beginning of line

  je .prev_row      ; if it is, move it to the previous row

  

  ; not at beginning of line, can just decrement cursor X and reset

  dec   dl          ; decrement X

  mov   ah, 2       ; reset cursor position

  mov   bh, 0

  int   0x10

  ret


  .prev_row:

    ; if cursor is at first row, leave it there

    cmp dh, 0

    je  .move_cursor

    

    ; cursor not at top row, move to end of previous line

    dec dh            ; decrement X

    mov dl, 79        ; columnn is at end of previous line

    

    .move_cursor:

      mov ah, 2       ; set cursor position

      mov bh, 0

      int 10h

      ret

Note that I fixed your wraparound problem.

I have a feeling there's something really obvious that we're overlooking here. Are you sure you've got your character codes correct?
sudo rm -rf /

#7
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Is this any better, when it comes to neatness?

;Initialization and stuff

mov bl,0x07

mov ebp,stackb

mov esp,stacke

mov dx,0x800

mov es,dx


;The beggining of the loop

loop:

call poll	;Poll for keys

mov ah,0x0e	;Interrupt number

cmp al,0x08	;Check for backspace

je .backspace	;Handle backspace

cmp ax,4b00h	;Check if the left arrow key was pressed

je .cursor_left	;Handle left arrow key

cmp ax,4d00h	;Check if the right arrow key was pressed

je .cursor_right	;Handle right arrow key

jmp .else	;Handle normal keystroke


.cursor_left:

push ax		;Save all of the registers

push bx

push cx

push dx

call cursor_left	;Decrement the cursor (or at least try to)

pop dx		;Restore the registers

pop cx

pop bx

pop ax

jmp loop	;Go back to the beginning


.cursor_right:

push ax		;Save all of the registers

push bx

push cx

push dx

call cursor_right	;Increment the cursor

pop dx		;Restore the registers

pop cx

pop bx

pop ax

jmp loop


.backspace:

cmp di,0	;I have no idea what this is for, and don't have a clue why I put this here,

je loop		;but I am not taking it out in case it does something useful

dec dx		;Decrement pointer

mov cx,bx

mov bx,dx	;I don't know why I made this so complicated

mov byte [es:bx],al	;Remove one entry in the array

mov bx,cx

mov al,8	;Move the cursor left, overwrite with a space, and move it back again

int 0x10

mov al,' '

int 0x10

mov al,8

int 0x10

jmp loop	;Go back to the beginning


.else:

int 0x10	;Display normal keystroke

mov cx,bx

mov bx,dx

mov byte [es:bx],al	;Put key into array

mov bx,cx

inc dx		;Increment pointer

jmp loop	;Go back to the beggining


poll:

mov ah,0 	;Int 16h function 0 get keystroke

int 0x16

cmp ax,0x1f13	;Check for Ctrl+S I don't know why I put this in such an akward place

je write	;Write to floppy if Ctrl+S is pressed

ret		;Return


pause:

push ax		;I don't even use this function, it's just here

mov ah,0	;to pause the program if I need to

int 0x16

pop ax

ret


write:

mov ah,3	;Int 13h function 3 write to drive

mov al,5	;Write 5 sectors

mov ch,0	;Cylinder number 0

mov cl,2	;Sector number 2 (although it writes starting at 5 instead)

mov dh,0	;Head number 0

mov dl,0	;Drive number 0

xor bx,bx	;Set BX to 0

int 0x13	;Write

jmp halt	;Halt the program


cursor_left:

mov ah,3	;Int 10h function 3 get cursor position

mov bh,0	;Page number 0

int 0x10

cmp dl,0	;Check if the column number is 0

jne .else	;If not, then jump to move the cursor like normal


.prevrow:

cmp dh,0	;Check if the row number is 0

je .row0	;If so, do nothing

mov dl,79	;Move back to the previous row

dec dh

mov ah,2

int 10h

xor bh,bh

ret


.row0:

ret


.else:

dec dl

int 10h

xor bh,bh

ret


cursor_right:

mov ah,3

mov bh,0

int 10h

cmp dl,79	;Check if the curosr is in column 79

jne .else	;If not, then jump to move the cursor like normal


.nextrow:

mov dl,0	;Move down to the next row

inc dh

mov ah,2

int 10h

xor bh,bh

ret


.else:

inc dl

int 10h

xor bh,bh

ret


halt:

cli

hlt	;Halts the program with a loop of HLT's

jmp halt


section .bss

stackb: resb 4096	;Reserve space for the stack

stacke:

I am almost 100% sure those are the right codes for the arrows. I got them Here, at the bottom of the page.
Latinamne loqueris?

#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
I haven't forgotten about you, just been busy. I'm going to try and come up with something this weekend, but I can't make any promises. How are you testing this, by the way?
sudo rm -rf /

#9
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Sorry for replying so late. I have been testing this in VirtualBox.
Latinamne loqueris?

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Ok, I got this working as part of a larger project I started (all your fault :D )

; -- init stuff --

main_loop:

  call  get_key


  ; Check what kind of key we used. Left arrow moves back a character, right

  ; arrow moves forward.

  cmp   ax, 0x4d00        ; Right arrow

  je    right_arrow

  cmp   ax, 0x4b00        ; Left arrow

  je    left_arrow

  cmp   ax, 0x4800        ; Up arrow

  je    up_arrow

  cmp   ax, 0x5000        ; Down arrow

  je    down_arrow


  ; Some other key. If AL is zero, then it's some control key. Otherwise it's

  ; just a regular ASCII value which we can put in our buffer.

  cmp   al, 00h

  je    main_loop


  mov   [es:di], al

  jmp   main_loop


right_arrow:

  cmp   BYTE [cursor_x], 79

  jae   main_loop


  add   di, 2

  inc   BYTE [cursor_x]

  call  update_cursor

  jmp   main_loop


left_arrow:

  cmp   BYTE [cursor_x], 0

  je    main_loop


  sub   di, 2

  dec   BYTE [cursor_x]

  call  update_cursor

  jmp   main_loop


up_arrow:

  cmp   BYTE [cursor_y], 0

  je    main_loop


  sub   di, 160

  dec   BYTE [cursor_y]

  call  update_cursor

  jmp   main_loop


down_arrow:

  cmp   BYTE [cursor_y], 24

  jae   main_loop


  add   di, 160

  inc   BYTE [cursor_y]

  call  update_cursor

  jmp   main_loop


get_key:

  ; -- removed other stuff here --

  mov   ah, 00h

  int   16h

  ret


update_cursor:

  mov   ah, 0x02

  mov   bl, 0x00

  mov   dh, [cursor_y]

  mov   dl, [cursor_x]

  int   10h

  ret



cursor_x: db 0

cursor_y: db 0


sudo rm -rf /

#11
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Thanks! I can't run it at the moment because I'm not at my home computer, so I'll run it when I can. I have another question too: How can I control the cursor without using BIOS interrupts?
Latinamne loqueris?

#12
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
You need to write to the VGA CTR controller ports. In my little program, I use DI as a pointer to the current location to write to, which is also the cursor's location.

update_cursor:

  mov   cx, di            ; CX = DI, pointer into video memory

  shr   cx, 1             ; Divide by 2 because there are 2 bytes per character

  mov   al, 0x0e          ; 0x0e is index to cursor location (high) register

  mov   dx, 0x03d4        ; We want to write to port 0x03d4

  out   dx, al            ; Send index of the CRT register to the controller

  mov   dx, 0x03d5        ; Write to port 0x03d5 with HIGH byte of cursor loc.

  mov   al, ch            ; AL = high byte of the cursor's location

  out   dx, al            ; Send high byte of cursor's location to CRT register

  mov   dx, 0x03d4        ; Prepare for register write access again

  mov   al, 0x0f          ; 0x0f is index to cursor location (low) register

  out   dx, al            ; This time send LOW byte of cursor location

  mov   dx, 0x03d5        ; Writing to port 0x03d5

  mov   al, cl            ; AL = low byte of cursor location

  out   dx, al            ; Send

  ret


The cursor location is the same as the character index, which is the same as the pointer into the video buffer divided by two. (There are two bytes per character; the first is the actual character, the second is the color/attribute information.) Since this can't be represented in one byte, you need to send each byte of the cursor location. You tell the CRT controller that you want to access a register by writing the index of that register to port 0x03d4, and then read from/write to that register. In this case, the index for the high byte of the cursor location is 0x0e, and the low byte goes to register 0x0f.

Edit: I have a PDF with all the VGA port numbers and other fun things. Somewhere.
sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users