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 haltAny help would be appreciated :)
44 replies to this topic
#1
Posted 02 October 2010 - 05:40 AM
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:
Latinamne loqueris?
|
|
|
#2
Posted 02 October 2010 - 04:07 PM
#3
Posted 02 October 2010 - 07:12 PM
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
Posted 06 October 2010 - 03:50 PM
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
Posted 06 October 2010 - 04:04 PM
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
Posted 06 October 2010 - 05:07 PM
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 retyou 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 retNote 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
Posted 07 October 2010 - 04:54 AM
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
Posted 09 October 2010 - 03:37 PM
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
Posted 10 October 2010 - 02:11 PM
#10
Posted 10 October 2010 - 08:44 PM
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
Posted 11 October 2010 - 02:01 PM
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
Posted 11 October 2010 - 02:50 PM
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.
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.
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


Sign In
Create Account


Back to top









