The first version of my program used DOS Function 13h.
The second version of my program used BIOS Function 10h
I now want to do the third version using direct hardware output. I have read the parts of the books that explain the screen is divided into 80x25 on a VGA (not bothered about detecting CGA and all that so program uses memory address 0B800h for colour VGA, DOSBox being great and all, and my desire to move to Win Assembler sometime before im 90 years old) monitors. I have read that each character on the hardware screen is 2 bytes (1 for the attribute and one for the character itself, therefore you have 80x25x2=4000 bytes). The odd bytes describe the attribute, and the even bytes the ASCII character.
But my problem is this. No matter how I try, I cant get my program to output a simple black and white (which is just the attribute, I assume I can change this reasonably easily) string (which is just an array of bytes) 5 lines from the top of the screen, and 20 characters in from the left edge (which is just the number of blank characters away from a zero based index with 4000 bytes long). (if my calc is correct that is 5x80=400+20=420x2=840 is the starting position of my string within the array of 4000 bytes)
How do I separate the attribute from the character (I got it to work partially but it only shows every second character, then a bunch of random junk (thats how I figured I need some sort of byte pair for the attribute and text), or how do I set it up such that both are recognised together or how is that done. How do I control he position of the text on the screen once the calcs are made. Where am I going wrong.
I have tried looking around the web for this seemingly simple question but am unable to find a solution. Is there anyone who used to program in DOS and x86 Assembly that can tell me how to do this easy little program by not using BIOS or DOS functions, just with the hardware.
I would really appreicate a simple code snippet if possible. Or a refrence to some site or free e-book. I dont want buying a big book on dos console programming which will end up useless when I move to windows shortly. The only reason I am focused on this is because I want to learn true assembly, not some macro language or some pretensious high level language that claims to be assembly.
I am trying to build a library of routines that will make Assembly easier to learn so people dont have to work though all the 3 to 6 chapters across 10 books of theory esentially explaining again and again the same stuff when really all that is needed is enough to know how to get some output, assign values to variables, get some input, and do some loops and decisions. The theory can come along later, and by the time they get to loops and decisions most people will have done enough assembler to have all the theory anyway. I beleive assembly should be taught no different than any other language starting with a simple hello world program then getting input ect. I want to make this possible.
One other note, I know for a fact the problem is NOT with DOSBox as I have a very old PC running true MS-DOS V6.2 and the program still doesnt work (but gives almost identical output). In fact, DOSBox actually runs some of my old programs even better than True dos. Gem desktop being one example. Just wanted to get that cleared before people try suggesting its a problem with the emulator. It cant be, not with such simple programs. No im afraid the problem is with my little brain not fully understanding what is needed.
Can anyone out there please help!!
Below is the program I used (MASM 6.1 Under DOSBox on Win 7 64-bit). It uses BIOS Intrrupt 10h Function 13h sub function 0. I want to do the same stuff using direct hardware IO.
.model small .stack .data ;part of the program containing data ;Constants - None ;Variables MyMsg db 'Hello World' .code Main: GetAddress: mov ax,@data ;Gets address of data segment mov es,ax ;Loads segment address into es regrister mov bp,OFFSET MyMsg ;Load Offset into DX SetAttributes: mov bl,01001111b ;BG/FG Colour attributes mov cx,11 ;Length of string in data segment SetRowAndCol: mov dh,24 ;Set the row to start printing at mov dl,68 ;Set the column to start printing at GetFunctionAndSub: mov ah,13h ;BIOS Function 10h - String Output mov al,0 ;BIOS Sub-Function (0-3) Execute: int 10h ;BIOS Interrupt 10h EndProg: mov ax,4c00h ;Terminate program return 0 to OS int 21h ;DOS Interrupt 21h end Main end
Below is what I currently have done re hardware IO. Obviously its not complete, but I am trying to get the same effect as the above program.
.model small .stack .data CR equ 13h LF equ 10h MyMsg db 'Hello World' ;MyMsg db 00001111b,'H' ;Was just trying something diff here ; db 00001111b,'E' ;thinking attribute / character byte pair might work. ; db 00001111b,'L' ;but it didnt. ; db 00001111b,'L' ; db 00001111b,'O' ; db 00001111b,' ' ; db 00001111b,'W' ; db 00001111b,'O' ; db 00001111b,'R' ; db 00001111b,'L' ; db 00001111b,'D' ScreenSeg dw 0B800h .code Main: SetupSource: mov dx,@data mov ds,dx ;src seg mov dx,offset MyMsg mov si,dx ;src ofset (eol 22) SetupTarget: mov es,MyMsg ;tar seg (video buffer) mov di,3 ;tar ofset (eol 23) mov cx,22*80 ;wrds to be scrolled (80x22) (22 lines) std ;direction - down rep movsw ;write char and attr cld ;direction - up ;Below are some alternates I was trying ; mov dx,@data ; lea si,MyMsg ; mov ax,@data ; lea di,MyMsg ; mov cx,22 ; cld ; rep movsb ;Some more alternates here ;; mov ax, 40h ;; mov ds, ax ;; mov cx, 22 ;; mov si, cs ;; mov ds, si ;; lea si, MyMsg ;; mov di, ScreenSeg ;; mov es, di ;; xor di, di DoMove: ; cld ; rep movsw EndPrg: mov ax, 4C00h int 21h end Main
So given all the above where am I going wrong.