25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

33KB

Developing Your Own 32-Bit Operating System — Chapter-26: Video Code

  • Source: /library/Developing Your Own 32-Bit Operating System/source-file.pdf
  • PDF pages: 593–612
  • Pages without text: 593

26 Video Code

0 Part TV ■ The Operating System Source Code The code presented in this chapter implements a VGA text-based video driver. This driver does not use the standard MMURTL device driver interface. The reason it doesn't use the interface is that it was one of the first things written for the operating system. All of my earliest testing depended on being able to see results from test programs. Virtual Video Concept In a multitasking operating system that supports text-based video, more than one application at a time may need to write data to or read data from the video screen. This would not be possible if all the programs running wrote to the real video screen buffer. In VGA Text mode, which is the default setup in BIOS on machines that have VGA monitors, eight hardware buffers are actually available. You could use those and switch between them, but doing so would limit you to eight active programs. To allow as many programs as possible, you allocate a page of system memory (4096 bytes) for zac\v job (program) as a virtual video buffer. This prevents future problems. If I want to add a graphical user interface, text-based programs will still run and can be displayed in a window directly from each job's buffer if needed. The video status for each job is kept in its job control block (JCB). The status includes screen coordinates, video screen size, video mode, a pointer to the job's virtual buffer, and a pointer to the current active buffer. When a new task is assigned to the video screen, the contents of its virtual buffer are copied to the real screen buffer, and the pointer to the current active buffer is changed to point to the real video screen buffer. The reverse occurs for the old job (the one that was using the real screen). The real buffer is copied into the job's virtual buffers, and the job's active pointer is changed back to its own buffer. VGA Text Video Many books have been written about how to control standard VGA video hardware, and the hardware seems fairly standardized as well. I won't give much detail on how it works for two reasons. First, I'm not a video “guru,” and second, I let the BIOS code in the machine set up the video hardware for the standard VGA Text mode. You may want to set up the video differ- ently in your system. If so, the shelves of your local bookstore are filled with brain dumps from people who have much more knowledge than I. You'll find implementing this code was really a simplicity issue with me. I control the registers that deal with cursor positioning and which video buffer is used. I use only one. These registers are defined in the data section of the code listing later in this chapter.

Chapter 26 ■ Video Code H The Video Code You will notice, no doubt, that all of the video code in this chapter is in assembler (as is most of MMURTL). When I first started testing MMURTL, assembler was all I could work with, and I needed to see things. You can only work “blind” for so long. A very important point for you to know is that this code is completely re-entrant, with the exception of those calls that actually manipulate video hardware. Only one program on the system should act as a video and keyboard manager (such as the MMURTL Monitor). The first items in the source file are the data declarations and the INCLUDE files, which de- fine certain constant values (all of the MMURTL source files are set up to have these items first). These include constants for the video hardware. The code in Listing 26.1 presents the initial items in the source file. Listing 26.1. Video constants and data. ; Index port for CRTC ;Data port for CRTC ; Register for lo byte of Video address ; Register for lo byte of Video address ; Register for lo byte of Cursor address ;Register for lo byte of Cursor address ;CRT Reg 0C HiByte address value ;CRT Reg 0D LoByte address value PUBLIC ddVidOwner DD 1 ;JCB that currently owns video ; Default to monitor (Job 1) End of Data & Equates BEGIN INTERNAL CODE FOR VIDEO .DATA .INCLUDE MOSEDF.INC .INCLUDE JOB. INC ;Video Equates and Ty CRTCPortl EQU 03D4h CRTCPort2 EQU 03D5h CRTCAddHi EQU 0Ch CRTCAddLo EQU 0Dh CRTCCurHi EQU 0Eh CRTCCurLo EQU 0Fh CRTC0C DB 0 CRTC0D DB 0 CODE EXTRN GetpJCB NEAR EXTRN GetpCrntJCB NEAR EXTRN ReadDbgKbd NEAR EXTRN GetCrntJobNum NEAR The InitVideo( ) makes video screen 0 (zero) the default screen for standard VGA hardware. The VGA text base address is 0B8000h. This address is a constant in one of the INCLUDE

c-ja Part TV ■ The Operating System Source Code files called VGATextBase. InitVideo( ) is called only once, when the operating system is ini- tialized. Data ports on standard VGA video hardware are accessed as an array with an index. See Listing 26.2. Listing 26.2. Code to initialize video. InitVideo: MOV AL, CRTCAddHi ; Index of hi byte MOV DX, CRTCPortl ; Index Port OUT DX, AL MOV AL, CRTC0C ;hi byte value to send MOV DX, CRTCPort2 ;Data Port OUT DX, AL MOV AL, CRTCAddLo ; Index of lo byte MOV DX, CRTCPortl ; Index Port OUT DX, AL MOV AL, CRTC0D ;lo byte value to send MOV DX, CRTCPort2 ;Data Port OUT DX, AL RETN ; BEGIN PUBLIC CODE FOR VIDEO The SetVidOwner(ddJobNum) call selects the screen that you see. This call is used by the moni- tor in conjunction with the SetKbdOwner( ) call to change which application gets the keystrokes and video; the application should be the same for both. The internal debugger is the only code that will use this call and not move the keyboard at the same time. The debugger was given its own keyboard code so I could debug the real keyboard code. Don't even ask how I debugged the debugger keyboard code. It certainly wasn't easy. The parameter (ddJobNum) is the new job to get the active screen (the one to be displayed). As always, if the call is successful, EAX returns 0. See Listing 26.3. Listing 26.3. Code to set the video owner. ddJobVidCV EQU DWORD PTR [EBP+12] PUBLIC _SetVidOwner: PUSH EBP MOV EBP, ESP MOV EAX, ddJobVidCV CMP EAX, ddVidOwner JNE ChgVid01 XOR EAX, EAX JMP ChgVidDone ChgVid01 : CALL GetpJCB CMP DWORD PTR [ EAX+pVidMem] JNE ChgVid02 Already own it? No Yes ; Leaves ptr to new vid JCB in EAX ;Got valid video memory??? ;Yes

Chapter 26 ■ Video Code H MOV EAX, ErcVidNum ;NO! Give em an error! JMP ChgVidDone ChgVid02: ;Save data on screen to CURRENT job's pVirtVid MOV EAX, ddVidOwner CALL GetpJCB PUSH VGATextBase ;Source MOV EBX, [EAX+pVirtVid] ;Destination PUSH EBX PUSH 4000 ;Size of video CALL FWORD PTR _CopyData ;Do it! ;Make pVidMem same as pVirtVid for CURRENT OWNER MOV EAX, ddVidOwner CALL GetpJCB ; Leaves ptr to new vid JCB in EAX MOV EBX, [EAX+pVirtVid] MOV [EAX+pVidMem], EBX ;Update current video owner to NEW owner MOV EAX, ddJobVidCV ; MOV ddVidOwner, EAX ;Copy in Data from new pVirtVid MOV EAX, ddVidOwner CALL GetpJCB MOV EBX, [EAX+pVirtVid] ; Source PUSH EBX PUSH VGATextBase ;Destination PUSH 4000 ;Size of video CALL FWORD PTR _CopyData ;Do it! ;Make new pVidMem real video screen for new owner MOV EAX, ddVidOwner CALL GetpJCB MOV EBX, VGATextBase MOV [EAX+pVidMem], EBX ;Set Cursor position MOV EAX, ddVidOwner CALL GetpJCB MOV ECX, EAX MOV EBX, [ECX+CrntX] ;Get current X for new screen MOV EAX, [EBX+CrntY] ;Current Y CALL HardXY ;Set it up XOR EAX, EAX ;No Error ChgVidDone: MOV ESP, EBP ; POP EBP ; RETF 4 The SetNormVid(dCharAttr) selects the normal background attribute used by ClrScr() and ScrollVid( ) on the screen. The parameter dCharAttr (listed as ddNormVid in the EQU statement

cjf Part PV ■ The Operating System Source Code in Listing 26.4) is the attribute value used in standard video operations on the current screen. TheClrScr(), EditLine(), and ScrollVid() calls use this value. It is saved in the JCB for each job. The EAX register returns zero for no error, and you'll notice that's all it can return. See Listing 26.4. Listing 26.4. Code to set normal video attribute. ddNormVid EQU DWORD PTR [EBP+12] PUBLIC _SetNormVid: PUSH EBP ; MOV EBP, ESP ; CALL GetpCrntJCB ;pJCB -> EAX MOV EBX, ddNormVid ; MOV [EAX+NormAttr], EBX ; XOR EAX, EAX POP EBP ; RETF 4 The GetNormVid(pVidRet) call returns the value to the normal screen attribute. This call gets the value that is set with the SetNormVid ( ) call. This call expects a pointer to a byte where this value is returned. If you've noticed that you only return a byte although you passed in a word to SetNormVid ( ) , you are correct. There's no mistake; the upper three bytes really aren't used (yet). See Listing 26.5. Listing 26.5. Code to get the normal video attribute. pdNormVidRet EQU DWORD PTR [EBP+12] PUBLIC _GetNormVid: PUSH EBP ; MOV EBP, ESP ; CALL GetpCrntJCB ;pJCB -> EAX MOV EBX, [EAX+NormAttr] ; MOV ESI, pdNormVidRet ; MOV [ESI], BL ; XOR EAX, EAX POP EBP ; RETF 4 The GetVidOwner(pdJobNumRet) function returns the job number currently assigned the active video screen. See Listing 26.6. Listing 26.6. Code to get the current video owner. pVidNumRet EQU DWORD PTR [EBP+12] PUBLIC GetVidOwner:

Chapter 26 ■ Video Code PUSH EBP MOV EBP, ESP MOV ESI, pVidNumRet MOV EAX, ddVidOwner MOV [ESI], EAX XOR EAX, EAX MOV ESP, EBP POP EBP RETF 4 no error obviously The ClrScr() call clears the screen for the executing job. If this is the active screen, the real video buffers get wiped. If not, only the caller's virtual video buffer gets cleared. This call uses the value that you set in SetNormVid ( ) for the color attribute and a space for the character. See Listing 26.7. Listing 26.7. Code to clear the screen. PUBLIC _ClrScr: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX MOV EDI,[EBX+pVidMem] MOV EAX, [EBX+NormAttr] ;Attr SHL EAX, 8 MOV AL, 20h MOV DX, AX SHL EAX, 16 MOV AX, DX MOV ECX,0400h CLD REP STOSD PUSH 0 PUSH 0 CALL FWORD PTR _SetXY MOV ESP, EBP POP EBP RETF Leaves ptr to current JCB in EAX EDI points to the caller's video memory ;Fill Char & Attr Ere in EAX on Return The TTYOut(pTextOut, ddTextOut, ddAttrib) function translates the text buffer pointed to with pTextOut into a stream of characters placed in the caller's video buffer. The beginning x and y coordinates are those found in the caller's JCB. The number of chars of text in the buffer you are pointing to is ddTextOut, and ddAttrib is the attribute or color you want for all of the characters. The following characters in the stream are interpreted thus (listed in hex): I OA — Line feed. The cursor (next active character placement) will be on the following line at column 0. If this line is below the bottom of the screen, the entire screen will be scrolled up one line, the bottom line will be blanked, and the cursor will be placed on the last line in the first column.

B Part IV The Operating System Source Code ■ OD — Carriage return. The cursor will be moved to column 0 on the current line. ■ 08 — Backspace. The cursor will be moved one column to the left. If the cursor is already at column 0, Backspace will have no effect. The Backspace is nondestructive (no character values are changed). I will eventually add 07h (Bell), 07F (Delete), and OCh (Form Feed). If you want to go beyond these, you may want to consider writing an ANSI device driver instead of modifying this code. Listing 26.8. Listing 26.8. Code for TTY stream output to screen. pTextOut EQU DWORD PTR [EBP+20] sTextOut EQU DWORD PTR [EBP+16] dAttrText EQU DWORD PTR [EBP+12] DataByte EQU BYTE PTR [ECX] PUBLIC _TTY0ut : PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX MOV EAX, STextOut OR EAX, EAX JZ TTYDone ; Leaves ptr to current JCB in EAX ;make sure count isn't null TTY00 : MOV EAX,[EBX+CrntX] MOV EDX,[EBX+CrntY] MOV ECX.pTextOut EAX has CrntX (col) EDX has CrntY (line) CMP DataByte, 0Ah JNE TTY02 INC EDX CMP EDX,[EBX+nLines] JB TTY06 JMP TTYScr LF? Equal to or past the bottom? No Yes, goto scroll CMP DataByte, 0Dh JNE TTY03 MOV EAX.0 JMP TTY06 CR? CMP DataByte, 08h JNE TTY04 CMP EAX.0 JE TTY04 DEC EAX JMP TTY06 Backspace? PUSH EBX ;Save pointer to VCB

Chapter 26 Video (ode PUSH EAX PUSH EDX PUSH ECX PUSH 1 MOV ECX.dAttrText PUSH ECX CALL FWORD PTR POP EBX CMP EAX, 0 JNE TTYDone MOV EAX, [EBX+CrntX] MOV EDX, [EBX+CrntY] INC EAX CMP EAX, [EBX+nCols] JNE TTY06 MOV EAX.0 INC EDX CMP EDX,[EBX+nLines] JNE TTY06 X (Param 1) Y (Param 2) pointer to text char (Param3) Param 4 (nchars) Param 5 PutVidChars ; ; restore ptr to VCB ;Next column ;Make cursor follow past the bottom? No - goto 06 else fall thru DEC EDX PUSH EAX PUSH EBX PUSH ECX PUSH EDX ; back up one line ;Save registers (scroll eats em) PUSH 0 PUSH 0 PUSH 80 PUSH 25 PUSH 1 CALL FWORD PTR POP EDX POP ECX POP EBX POP EAX ;fUP (non zero) ScrollVid ; Ignore error ; restore registers :Fall thru to TTY06: PUSH EBX save ptr to pJCB PUSH EAX PUSH EDX CALL FWORD PTR SetXY TTYDone: POP EBX CMP EAX, 0 JNE TTYDone DEC sTextOut JZ TTYDone INC pTextOut JMP TTY00 MOV ESP, EBP POP EBP RETF 12 ;Restore ptr to VCB Go back for next char

I
580 Part PV ■ The Operating System Source Code The PutVidAttrs(ddCol, ddLine, sChars, dAttr) call sets screen colors (attributes) for the positions and number of characters specified, without affecting the current TTY coordinates or the character data. It is independent of the current video “stream.” PutVidAttrs( ) is a fill function and does not set multiple independent attributes. See Listing 26.9. Listing 26.9. Code to screen video attributes. OADDX EQU DWORD PTR [EBP+24] ;Param 1 COLUMN OADDY EQU DWORD PTR [EBP+20] ;Param 2 LINE sADDChars EQU DWORD PTR [EBP+16] ;Param 3 sChars sADDColor EQU DWORD PTR [EBP+12] ;Param 4 Attr PUBLIC _PutVidAttrs: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX MOV EDI, [EBX+pVidMem] MOV EBX.oADDx SHL EBX.1 MOV EAX.oADDy MOV ECX,0A0h MUL ECX ADD EAX, EBX CMP EAX,0F9Eh JBE PutAttrs00 MOV EAX, ErcVidParam JMP PcADone PutAttrs00: MOV ECX, sADDChars OR ECX, ECX JZ PcADone ADD EDI, EAX MOV EAX, SADDColor CLD pcAMore: pcADone: INC EDI STOSB LOOP pcAMore XOR EAX, EAX MOV ESP, EBP POP EBP RETF 16 ; Leaves ptr to current JCB in EAX ; point to this VCBs video memory ;x Position ; Times 2 ;y Position ;Times 160 (char/attrs per line) ; Times nColumns ;Last legal posn on screen ;Pass the char value ;Move Color in ;No Error! The PutVidChars(ddCol, ddLine, pChars, sChars, ddAtt rib) call places characters on the screen without affecting the current TTY coordinates or the TTY data. It is independent of the current video “stream.” The parameters include the position (column and line), a pointer to the characters to be placed, the count of characters, and the attribute.

Chapter 26 Video Code I
581 The starting position in screen memory is (Line * 80 + (Column*2) ). You alternate between characters and attributes as you move through screen memory because this is how the video hardware interprets its buffers for display (for example, put character, then color, then charac- ter, then color, and so on). See Listing 26.10. Listing 26.10. Code to place video characters anywhere on the screen. ODDX ODDY pDDChars sDDChars sDDColor EQU DWORD PTR [EBP+28] ;Param 1 COLUMN EQU DWORD PTR [EBP+24] ; Param 2 LINE EQU DWORD PTR [EBP+20] EQU DWORD PTR [EBP+16] EQU DWORD PTR [EBP+12] Param 3 pChars Param 4 sChars Param 5 Attr PUBLIC _PutVidChars: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX MOV EDI, [EBX+pVidMem] MOV EBX.oDDx SHL EBX.1 MOV EAX.oDDy MOV ECX,0A0h MUL ECX ADD EAX, EBX CMP EAX,0F9Eh JBE PutChars00 MOV EAX, ErcVidParam JMP PcDone PutChars00: MOV ECX, sDDChars OR ECX, ECX JZ PcDone MOV ESI, pDDChars ADD ED I, EAX MOV EAX, sDDColor CLD Leaves ptr to current JCB in EAX ; point to this VCBs video memory ;Times 2 ; Times 160 ; Times nColumns ;Last legal posn on screen pcMore: pcDone: MOVSB STOSB LOOP pcMore XOR EAX, EAX MOV ESP, EBP POP EBP RETF 20 ;Move Char in ;Move Color in ;No Error! The GetVidChar(ddCol, ddLine, pCharRet, pAttrRet) call returns the current character and attribute from the screen coordinates you specify. Whether or not the caller is the active video screen doesn't matter. This is because the pointer in the JCB is set to either the virtual screen or the real one, and this is the pointer you use to acquire the attribute. See Listing 26.1 1.

H Part IV The Operating System Source Code Listing 26.1 1 . Code to get a character and attribute. oGDDX EQU DWORD PTR [EBP+24] ;Param 1 COLUMN OGDDY EQU DWORD PTR [EBP+20] ;Param 2 LINE pGDDCRet EQU DWORD PTR [EBP+16] ;Param 3 pCharRet pGDDARet EQU DWORD PTR [EBP+12] ;Param 4 pAttrRet PUBLIC GetVidChar: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB ; Leaves ptr to current JCB in EA MOV EBX, EAX MOV EDI, [EBX+pVidMem] ; point to this VCBs video memory MOV EBX,oGDDx SHL EBX.1 ; Times 2 MOV EAX , oGDDy MOV ECX,0A0h ; Times 160 MUL ECX ; Times nColumns ADD EAX, EBX CMP EAX,0F9Eh ;Last legal posn on screen JBE GetChar00 MOV EAX, ErcVidParam JMP PcGDone GetCharOO: ADD EDI, EAX ;EDI now points to char MOV ESI, pGDDCRet MOV AL, [EDI] MOV [ESI], AL ;Give them the char INC EDI ;Move to Attr MOV ESI, pGDDARet MOV AL, [EDI] MOV [ESI], AL ;Give them the Attr XOR EAX, EAX ;No Error! pcGDone: MOV ESP, EBP ■ POP EBP RETF 20 TheScrollVid(ddULCol, ddULline, nddCols, nddLines, ddfUp) function scrolls the described square area on the screen either up or down one line. If ddfUp is not zero, the scroll will be up. The line left blank is filled with NormAttr from JCB. The upper-left corner of the area to scroll is described by ddULCol and ddULLine. The size of the area is nddCols and nddLines. To scroll the entire screen up one line, the parameters are ScrollVid ( 0 , 0 , 80 , 25 , 1 ) . In this case, the top line is lost (not really scrolled), and the bottom line are blanked. In tact, it you specified ScrollVid (0,1 ,80,24,1 ), you would get the same results. See Listing 26.12. Listing 26.12. Code to scroll an area of the screen. OULX EQU DWORD PTR [EBP+28] ;Param 1 COLUMN oULY EQU DWORD PTR [EBP+24] ;Param 2 LINE nddCols EQU DWORD PTR [EBP+20] ;Param 3 pChars

Chapter 26 Video Code H nddLines EQU DWORD PTR ddfUP EQU DWORD PTR PUBLIC ScrollVid: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX MOV EAX, oULX CMP EAX, 79 JA svErcExit ADD EAX, nddCols CMP EAX, 80 JA svErcExit MOV EAX, OULY CMP EAX, 24 JA svErcExit ADD EAX, nddLines CMP EAX, 25 JA svErcExit CMP ddfUP, 0 JNE svUP0 Leaves ptr to current JCB in EAX Save pJCB & use in EBX ; Scroll UP? ;Yes... Scroll UP! Scroll DOWN begins MOV ADD MOV MUL MOV MOV ADD ADD ADD MOV SUB MOV MOV DEC EAX, EAX, ECX, ECX EDI, EDX, EDI, EDI, EDI, ESI, ESI, EBX, EAX, EAX OULY nddLines 160 ; First line ;Last line [EBX+pVidMem] EBX EAX OULX oULX EDI 160 ESI nDDLines times nBytes per line EDI points to video memory ( ;Save pJCB ;EDI is ptr to 1st dest line ;offset into line ;add again for attributes ;ESI is 1st source line ;Save in EBX for reload ;How many lines to move ;one less than window height MOV REP MOV MOV SUB MOV DEC JNZ MOV SHL MOV MOV MOV CLD REP XOR ;How many WORDS per line to move ;Move a line (of WORDS!) ; Reload Dest to next line ;Save again ECX, nddCols MOVSW EDI, EBX ESI, EDI ESI, 160 EBX, ESI EAX svDOWNI EAX, [EDX+NormAttr] ;Normal video attributes! ! ! EAX, 8 AL, 20h ; Space EDI, EBX ;Put the last line into EDI ECX, nddCols STOSW EAX, EAX ;No error

0 Part PV ■ The Operating System Source Code Listing 26.1 2. continued JMP svDone ;No... scroll down begins MOV EAX, OULY ; First line MOV ECX, 160 MUL ECX ;times nBytes per line MOV EDI, [EBX+pVidMem] ;EDI points to video memory 0,0 MOV EDX, EBX ;Save pJCB ADD EDI, EAX ;EDI is ptr to 1st dest line ADD EDI, OULX joffset into line ADD EDI, OULX ;add again for attributes MOV ESI, EDI ; ADD ESI, 160 ;ESI is 1st source line MOV EBX, ESI ;Save in EBX for reload MOV EAX, nDDLines ;How many lines to move DEC EAX ;two less than window height svUP1 : MOV ECX, nddCols ;How many WORDS per line to move REP MOVSW ;Move a line (of WORDS! ) MOV EDI, EBX ; Reload Dest to next line MOV ESI, EDI ADD ESI, 160 MOV EBX, ESI ;Save again DEC EAX JNZ SVUP1 MOV EAX, [EDX+NormAttr] ;Normal video attributes!!! SHL EAX, 8 MOV AL, 20h ; Space MOV EDI, EBX ;Put the last line into EDI SUB EDI, 160 MOV ECX, nddCols CLD REP STOSW XOR EAX, EAX ;No error JMP svDone svErcExit : ; Error exits will jump here MOV EAX, ErcVidParam svDone: MOV ESP, EBP ; POP EBP i RETF 20 The HardXY( ) call is used to support positioning the cursor in hardware. When a video call that repositions the cursor is made and the caller owns the real video screen, HardXY( ) is called to ensure that the hardware follows the new setting. This supports SetXY( ) and SetVidOwner( ). The parameters to this call are via registers; thus no stack parameters are used. EAX is set with the new y position and EBX is set with the new x position before the call is made. See Listing 26.13.

Chapter 26 Video Code Listing 26.13. Support code to set hardware cursor position. HardXY: MOV ECX, 80 MUL ECX ADD EAX, EBX MOV DX,CRTCPort1 PUSH EAX MOV AL.CRTCCurLo OUT DX.AL POP EAX MOV DX,CRTCPort2 OUT DX.AL SHR EAX, 08 PUSH EAX MOV DX,CRTCPort1 MOV AL.CRTCCurHi OUT DX.AL POP EAX MOV DX,CRTCPort2 OUT DX.AL RETN Line * 80 Line plus column Index register Index 0Fh for low byte Data register Send Low byte out shift hi byte into AL Index for High byte Send High byte out The SetXY(ddNewX, ddNewY) function positions the VGA cursor (Text mode) to the x and y position specified in the parameters ddNewX and ddNewY. If the caller also happens to own the real video screen buffer (being displayed), then the hardware cursor is also repositioned by a call to the internal support call HardXY( ) from Listing 26.13. See Listing 26.14. Listing 26.14. Code to set cursor position. NewX NewY EQU DWORD PTR EQU DWORD PTR [EBP+16] [EBP+12] PUBLIC SetXY: PUSH EBP MOV EBP, ESP CALL GetpCrntJCB MOV EBX, EAX Leaves ptr to current JCB MOV ECX, NewX MOV EDX.NewY MOV [EBX+CrntX],ECX MOV [EBX+CrntY],EDX Column Line This saves it in the VCB CALL GetCrntJobNum CMP EAX, ddVidOwner JNE GotoXYDone MOV EAX, NewY MOV EBX, NewX CALL HardXY ; Leaves ptr to current JCB in EAX ;If not on Active screen, skip it ; Setup to call HardXY

I cos I Part PV ■ The Operating System Source Code Listing 26.14. continued GotoXYDone: XOR EAX, EAX MOV ESP, EBP POP EBP RETF 8 No Error The GetXY(pddXRet , pddYRet) function returns the x and y cursor positions from the caller's job control block. The positions in the JCB are updated with each character placement, so this will be accurate even if the caller is not currently displayed on the real video screen. See Listing 26.15. Listing 26.15. Code to return current cursor position. pxret EQU DWORD PTR [EBP+16] pYret EQU DWORD PTR [EBP+12] PUBLIC GetXY: PUSH EBP ; MOV EBP, ESP ; CALL GetpCrntJCB ;L MOV EBX, EAX MOV EAX,[EBX+CrntX] ; MOV ESI.pXret MOV [ESI], EAX MOV EAX,[EBX+CrntY] ; MOV ESI.pYret MOV [ESI], EAX XOR EAX, EAX QXYDone MOV ESP, EBP ; POP EBP ; RETF 8 Leaves ptr to current JCB in EAX Column Line The EditLine(pStr, dCrntLen, dMaxLen, pdLenRet, pbExitChar, dEditAttr) function reads a line of text from the keyboard and puts it into the string pointed to by pStr. If pStr points to a valid string (dCrntLen > 0), the string is displayed. The editing of this string is done at the current x and y positions. You also specify the maximum length the string can be (dMaxLen), where you want the exit character returned (pbExitChar), and finally the attribute for the text you are editing (dEditAttr). The EditLine ( ) function probably shouldn't be included with the video code, but rather should be a library function. I added this call while doing a lot of testing; the call came in so handy as part of the operating system code that I just left it where it was. Display and keyboard are handled entirely inside of EditLine ( ). The following keys are recog- nized and handled inside:

Chapter 26 ■ Video Code |
587 ■ 08 — Backspace. A destructive backspace, this moves the cursor to the left, replacing char with 20h. ■ 20h-7Eh — ASCII text. Any of these places this character in the current x and y position and advances the position of the cursor. Any other key causes Edit line ( ) to exit, which returns the string in its current condition and also returns the key that caused Editline( ) to exit. See Listing 26.16. Listing 26.16. Code to edit a line on the screen. pEdString EQU DWORD PTR [EBP+32] ddSzCrnt EQU DWORD PTR [EBP+28] ddSzMax EQU DWORD PTR [EBP+24] pddSzRet EQU DWORD PTR [EBP+20] pExitKeyRet EQU DWORD PTR [EBP+16] dEditAttr EQU DWORD PTR [EBP+12] ; Local vars EditX and EditY hold position of first char of text ;CrntX is the cursor postion PosnX EQU DWORD PTR [EBP -04] EditX EQU DWORD PTR [EBP -08] EditY EQU DWORD PTR [EBP -12] KeyCode EQU DWORD PTR [EBP -16] PUBLIC _EditLine: PUSH EBP ; MOV EBP, ESP ; SUB ESP, 16 CMP ddSzCrnt, 80 ;Is it currently too long? JA BadEdit CMP ddSzMax, 80 ;Is Max len too long? JA BadEdit MOV EAX, ddSzCrnt CMP EAX, ddSzMax ;Is Crnt len > Max??? JA BadEdit LEA EAX, EditX ;Get current cursor posns in local vars PUSH EAX LEA EAX, EditY PUSH EAX CALL FWORD PTR GetXY CMP EAX, 0 JNE EditDone ;Bad Ere from call MOV EAX, EditX ADD EAX, ddSzCrnt MOV PosnX, EAX ;make PosnX end of string MOV ECX, ddSzMax SUB ECX, ddSzCrnt ;ECX how many bytes to zero JZ EdLn0l ;None to zero out

588 | Part PV ■ The Operating System Source Code Listing 26.1 6. continued MOV ESI, pEdString ADD ESI, ddSzCrnt MOV AL, 20h ; Initialize current string ;ESI ptr to 1st empty byte ;fill with spaces Edln00: MOV [ESI], AL INC ESI LOOP Edln00 EdLn01 : PUSH PosnX PUSH EditY CALL FWORD PTR SetXY CMP EAX, 0 JNE EditDone EdLn02: PUSH EditX ;Display curren PUSH EditY PUSH pEdString PUSH ddSzMax PUSH dEditAttr ;Attribute they CALL FWORD PTR PutVidChars CMP EAX, 0 JNE EditDone EdLn03: LEA EAX, KeyCode PUSH EAX CMP ddVidOwner, 2 ; Debugger??? JE EdLn035 PUSH 1 ;Wait for a key CALL FWORD PTR ReadKbd ;Get a key JMP SHORT EdLn036 EdLn035 CALL ReadDbgKbd EdLn036 MOV EAX, KeyCode AND EAX, 07Fh OR EAX, EAX JZ EdLn03 CMP EAX, 08h ; Backspace? JNE EdLn04 ;No - Next test EdLn037 CMP ddSzCrnt, 0 JE EdLn01 DEC PosnX DEC ddSzCrnt MOV ESI, pEdString MOV ECX, ddSzCrnt MOV BYTE PTR [ESI+ECX], 20h JMP Edln01 EdLn04: CMP EAX, 03h ;Left? JNE EdLn045 ;No - Next test JMP EdLn037 EdLn045 CMP EAX, 83h ;Num-Left? JNE EdLn046 ;No - Next test

Chapter 26 Video Code 589 JMP EdLn037 EdLn046 CMP EAX, 0Dh ;CR? JNE EdLn05 ;No - Next test JMP EdLn07 EdLn05: CMP EAX, 1Bh ; Escape? JNE EdLn06 ;No - Next test JMP EdLn07 EdLn06: CMP EAX, 7Eh ;Is it above text? JA Edl_n07 ;Yes, Exit! CMP EAX, 20h ;Is it below text?? JB EdLn07 ;Yes, Exit MOV ESI, pEdString ;It's really a char MOV ECX, ddSzCrnt MOV BYTE PTR [ESI+ECX], AL MOV ECX, ddSzMax CMP ddSzCrnt, ECX JAE EdLn01 INC PosnX INC ddSzCrnt JMP EdLn01 EdLn07: MOV ESI.pExitKeyRet MOV [ESI], AL MOV ESI.pddSzRet MOV EAX, ddSzCrnt MOV [ESI], EAX PUSH EditX jDisplay current string w/Norm Attrs PUSH EditY PUSH pEdString PUSH ddSzMax CALL GetpCrntJCB ; Leaves ptr to current JCB in EAX MOV EBX, [EAX+NormAttr] PUSH EBX ; Normal Attribute from JCB CALL FWORD PTR _PutVidChars ; Ignore error (we are leaving anyway) XOR EAX, EAX JMP EditDone BadEdit EditDone: MOV EAX, ErcEditParam ; ; MOV ESP, EBP POP EBP RETF 24 Relating MMURTL's Video Code to Your Operating System The video hardware on your platform will determine how much work you have to do to imple- ment a video interface. From this chapter, you can see that simplicity was my goal.

590 Part IV ■ The Operating System Source Code In this age of graphics, you no doubt will want to experiment with both character-based and graphical interfaces. I recommend you keep the virtual character video concept in mind, be- cause it allows both character-based and graphical interfaces to coexist on a system.

Powered by TurnKey Linux.