Hello,
I'm now wanting to do some things in Assembly using VESA. I've already know how to set the mode that I want, in this case 103h, that will set the resolution to 800x600x256(all according to Ralf Brown's Interrupt List), like this:
I want to know how could I draw some pixels to the screen, things like a line, or an X..
Best Regards,
Nathan Paulino Campos
I'm now wanting to do some things in Assembly using VESA. I've already know how to set the mode that I want, in this case 103h, that will set the resolution to 800x600x256(all according to Ralf Brown's Interrupt List), like this:
mov ax, 4F02h
mov bx, 103h
int 10h
I want to know how could I draw some pixels to the screen, things like a line, or an X..
Best Regards,
Nathan Paulino Campos
I don't know if the bios putpixel routine works in hi-res modes or not. Too slow to use, in any case, even in mode 13h!
You can throw pixels at A000:xxxx, just like in mode 13h (do you know how to do it in mode 13h?). The difference is that 64k won't cover the screen in hi-res modes. We have access to a 64k "window" or "bank" at a time. For the remainder of the screen, we have to "switch banks" (int 10h/4F05h), and start over at A000:0000. Switching banks is slow enough that you want to keep a "current bank" variable, and switch only if you have to. (an alternative is asking for a linear frame buffer - set a high bit in bx when doing int 10h/4F02h, but the address isn't accessable from "regular real mode", and the bios int isn't available from 32-bit code... sigh... "flat real mode" will do it, but you have to start in "real dos" to get there)
Drawing a horizontal line is easy. A vertical line is easy. A "45 degree" (depending on the shape of the pixels) line is easy. For an arbitrary line, look into "Bresenham's Algorithm" (last I knew, he had a homepage, but I can't find it now). He's got a circle algorithm, too.
Lemme attach an example, I guess... This isn't exactly what you want, but may give you ideas. Not recently tested, but I think it used to work. Some dead code in it... needs cleaning up... not today...
Best,
Frank
You can throw pixels at A000:xxxx, just like in mode 13h (do you know how to do it in mode 13h?). The difference is that 64k won't cover the screen in hi-res modes. We have access to a 64k "window" or "bank" at a time. For the remainder of the screen, we have to "switch banks" (int 10h/4F05h), and start over at A000:0000. Switching banks is slow enough that you want to keep a "current bank" variable, and switch only if you have to. (an alternative is asking for a linear frame buffer - set a high bit in bx when doing int 10h/4F02h, but the address isn't accessable from "regular real mode", and the bios int isn't available from 32-bit code... sigh... "flat real mode" will do it, but you have to start in "real dos" to get there)
Drawing a horizontal line is easy. A vertical line is easy. A "45 degree" (depending on the shape of the pixels) line is easy. For an arbitrary line, look into "Bresenham's Algorithm" (last I knew, he had a homepage, but I can't find it now). He's got a circle algorithm, too.
Lemme attach an example, I guess... This isn't exactly what you want, but may give you ideas. Not recently tested, but I think it used to work. Some dead code in it... needs cleaning up... not today...
Best,
Frank
; line.asm Draw a line using Bresenham's algorithmn
;
;
.model small
.stack 200h ; 512 byte stack
.data
vid_mode db 0
start_x dw 0
end_x dw 319
start_y dw 0
end_y dw 199
color db 2
diagonal_y_increment dw ?
diagonal_x_increment dw ?
short_distance dw ?
straight_x_increment dw ?
straight_y_increment dw ?
straight_count dw ?
diagonal_count dw ?
.code
start:
mov ax,@data
mov ds,ax
mov ah,0fh ; determine current video mode
int 10h
mov vid_mode,al ; move mode value into buffer
;set screen mode
mov ah,0
mov al,4 ; orig. value = 4
int 10h
mov cx,1
mov dx,1
mov di,end_y
sub di,start_y
jge keep_y
neg dx
neg di
keep_y:
mov diagonal_y_increment,dx
mov si,end_x
sub si,start_x
jge keep_x
neg cx
neg si
keep_x:
mov diagonal_y_increment,cx
cmp si,di
jge horz_seg
mov cx,0
xchg si,di
jmp save_values
horz_seg:
mov dx,0
save_values:
mov short_distance,di
mov straight_x_increment,cx
mov straight_y_increment,dx
mov ax,short_distance
shl ax,1
mov straight_count,ax
sub ax,si
mov bx,ax
sub ax,si
mov diagonal_count,ax
mov cx,start_x
mov dx,start_y
inc si
mov al,color
mainloop:
dec si
jz line_finished
mov ah,12
int 10h
cmp bx,0
jge diagonal_line
add cx,straight_x_increment
add dx,straight_y_increment
add bx,straight_count
jmp mainloop
diagonal_line:
add cx,diagonal_x_increment
add dx,diagonal_y_increment
add bx,diagonal_count
jmp mainloop
line_finished:
mov ah,0 ; function no. for read
int 1ah ; get the time of day count
add dx,36 ; add « second(9) delay to low word
mov bx,dx ; store end of delay value in bx
repeat:
int 1ah
cmp dx,bx
jne repeat
mov ah,0 ; restore original video mode
mov al,vid_mode ;
int 10h
exit:
mov ax,4c00h
int 21h
end start
I've tried, but I got this errors:
Any help?
C:\Documents and Settings\Nathan\Desktop>nasm vesa.asm
vesa.asm:5: error: attempt to define a local label before any non-local labels
vesa.asm:5: error: parser: instruction expected
vesa.asm:6: error: attempt to define a local label before any non-local labels
vesa.asm:6: error: parser: instruction expected
vesa.asm:8: error: attempt to define a local label before any non-local labels
vesa.asm:121: error: parser: instruction expected
C:\Documents and Settings\Nathan\Desktop>
Any help?
I've tried, but I got this errors:
C:\Documents and Settings\Nathan\Desktop>nasm vesa.asm
vesa.asm:5: error: attempt to define a local label before any non-local labels
vesa.asm:5: error: parser: instruction expected
vesa.asm:6: error: attempt to define a local label before any non-local labels
vesa.asm:6: error: parser: instruction expected
vesa.asm:8: error: attempt to define a local label before any non-local labels
vesa.asm:121: error: parser: instruction expected
C:\Documents and Settings\Nathan\Desktop>
Any help?
Perhaps it is not NASM syntax?
SpooK is correct. Skywalker's code is Masm/Tasm(?) syntax. I'll bet Japheth's JWASM would assemble it. (tries it... nope. Doesn't like "repeat" as a label name!?!? Macro command? Change to "repeat_loop"... yep!)
But we can beat it into Nasm syntax fairly easily...
This assembles as "nasm -f obj ...", and links with Alink (running under Linux) without complaints. This does *not* mean it is correct! I could have missed a spot or two. It has not been tested!
I don't even remember what mode 4 is. I'd have expected mode 13h. May need some modifications to upgrade it to VESA modes. Maybe a start...
Best,
Frank
But we can beat it into Nasm syntax fairly easily...
; line.asm Draw a line using Bresenham's algorithm
;
;
; Here's Nasm's first complaint. Masm/Tasm use '.' to begin directives,
; Nasm uses '.' to begin local labels. As it happens, I don't think we
; need it at all, in this case.
;.model small
; Same here, but we do want a stack... (named "stack",
; of type "stack")
;.stack 200h ; 512 byte stack
segment stack stack
resb 200h
; .data
segment data ; defaults should be okay here
vid_mode db 0
start_x dw 0
end_x dw 319
start_y dw 0
end_y dw 199
color db 2
; Nasm doesn't know '?'. Use "resw 1", or...
%define ? 0
diagonal_y_increment dw ?
diagonal_x_increment dw ?
short_distance dw ?
straight_x_increment dw ?
straight_y_increment dw ?
straight_count dw ?
diagonal_count dw ?
; .code
segment code ; defaults okay?
; Masm/Tasm use "end start" to define "start" as the entrypoint.
; Nasm uses the special symbol "..start".
;start:
..start:
; mov ax,@data
mov ax, data
mov ds,ax
mov ah,0fh ; determine current video mode
int 10h
; The distinction between a memory address and the contents
; of memory at that address is obviously an important one!
; Unfortunately, different assemblers do it differently!
; mov vid_mode,al ; move mode value into buffer
mov ,al ; move mode value into buffer
;set screen mode
mov ah,0
mov al,4 ; orig. value = 4
int 10h
; this is not a vesa mode!
mov cx,1
mov dx,1
mov di,
sub di,
jge keep_y
neg dx
neg di
keep_y:
mov ,dx
mov si,
sub si,
jge keep_x
neg cx
neg si
keep_x:
mov ,cx
cmp si,di
jge horz_seg
mov cx,0
xchg si,di
jmp save_values
horz_seg:
mov dx,0
save_values:
mov ,di
mov ,cx
mov ,dx
mov ax,
shl ax,1
mov ,ax
sub ax,si
mov bx,ax
sub ax,si
mov ,ax
mov cx,
mov dx,
inc si
mov al,
mainloop:
dec si
jz line_finished
mov ah,12
int 10h
; slow as molases!!! Call your own putpixel (suitable to your mode)
cmp bx,0
jge diagonal_line
add cx,
add dx,
add bx,
jmp mainloop
diagonal_line:
add cx,
add dx,
add bx,
jmp mainloop
line_finished:
mov ah,0 ; function no. for read
int 1ah ; get the time of day count
add dx,36 ; add « second(9) delay to low word
mov bx,dx ; store end of delay value in bx
repeat:
int 1ah
cmp dx,bx
jne repeat
mov ah,0 ; restore original video mode
mov al, ;
int 10h
exit:
mov ax,4c00h
int 21h
; end start
This assembles as "nasm -f obj ...", and links with Alink (running under Linux) without complaints. This does *not* mean it is correct! I could have missed a spot or two. It has not been tested!
I don't even remember what mode 4 is. I'd have expected mode 13h. May need some modifications to upgrade it to VESA modes. Maybe a start...
Best,
Frank
That's horrid. PITA to write a putpixel for, too. Mode 103h will be easier, actually...
Best,
Frank
Best,
Frank