5
votes

I want to draw a colored line in asm. I have to use AT&T syntax, on an x86 intel linux unit. I got pretty far already, but I'd like to know how to enter VGA-mode, or Mode-X, and how to put a pixel on the screen. Is there a function for that in a standard C library (like printf)?

Thanks a lot for your help. :)

.bss # Declaring uninitialized variables

.data # Declaring initialized variables

.text # Actual assembly code and constants

intro:  .asciz "Draw a line in VGA\n\n"
clr:    .asciz "Give a color \n"
optns:  .asciz "red (1), blue (2), white (3)\n"
res     .asciz "%d"
    ent:    .asciz "\n"

.global main            # Tell kernel where to start (visible from outside)

main: pushl %ebp # Push base pointer movl %esp, %ebp # Initialize base pointer pushl $intro # Push the string address call printf # Call the printf routine from C library addl $8, %esp

pushl $clr          # push color question on the stack
call printf         # Print it

subl $4, %esp               # Reserve stack space for variable
leal -4(%ebp), %eax             # Load address of stack var in eax
pushl %eax          # Push second argument of scanf
pushl $rets         # Push first argument of scanf
call scanf          # Call scanf

    movl 4(%ebp), %ecx              # mov the result in ecx
    cmpl $1, %ecx
    je red
    cmpl $2, %ecx
    je blue
    jne white

red: #... still working on this

    movl 0013h, %eax                # enter 320x200x256 mode
    int 10h                         # IS THIS CORRECT?

    movl $0, %ebx                   # set X to 0
    movl $0, %ecx                   # set Y to 0

    call draw                   # Call line routine

    movl 0003h, %eax                # IS THIS CORRECT?
    int 10h                         # return to text mode

    movl $0, (%esp)             # Make esp 0, indicating succesful termination
    call exit                       # Exit the program

draw:
call putpixel # pushl %ebp # Push the base pointer # movl %esp, %ebp # Initialize base pointer inc %ebx # increment X inc %ecx # increment Y cmpl $200, %ecx # check if Y => 200 jge end # if Y=> 200, jump to end jmp draw # loop

putpxl: #has to put a pixel at (%ebx, %ecx) and return to draw # should use the color from the main routine

end: movl %ebp, %esp # Remove local variables popl %ebp # Remove base pointer ret # return to main routine

2

2 Answers

2
votes

Best thing you could do would be to use a higher-level library, like SDL or Allegro. This way, your program will work on top of X11 and on non-VGA framebuffers (e.g: displays on embedded ARM-based devices).

Svgalib allowed to program for VGA and so-called SVGA graphics cards. Its development stopped years ago.

There are two ways to access VGA hardware:

  • Using registers
  • Using the VGA BIOS: this is the one you've tried. VGA BIOSes are written to run in real mode. To invoke them from protected mode, you would need to switch to vm86 mode. which is what LRMI (Linux Real Mode Interface, the opposite of DPMI) did.
2
votes

You are not allowed to do direct video (graphic mode) output in linux (protected OS). it was possible only in a dos (real-mode OS).

You can use framebuffer device or SDL, or libX11. But there is no reason why to do work with high-level libraries from the asm.

Int 10 is not allowed in linux directly (in user mode; the kernel must do low-level accesses).

e.g. this is 5 year old exact the same discussion http://www.gamedev.net/topic/368196-linux-assembler-int-10h/