DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Linked List in Data Structures and Algorithms
  • Troubleshooting Memory Leaks With Heap Profilers
  • Stop Running Two Data Systems for One Agent Query
  • Designing Self-Healing AI Infrastructure: The Role of Autonomous Recovery

Trending

  • Introduction to Tactical DDD With Java: Steps to Build Semantic Code
  • Why We Chose Iceberg Over Delta After Evaluating Both at Scale
  • No More Cheap Claude: 4 First Principles of Token Economics in 2026
  • Detecting Bugs and Vulnerabilities in Java With SonarQube
  1. DZone
  2. Data Engineering
  3. Data
  4. Controlling VGA Memory with x86 Assembly Code

Controlling VGA Memory with x86 Assembly Code

A quick tutorial on a lesser used, but still effective, web development language, x86 Assembly Code.

By 
Nadir Yaqoob user avatar
Nadir Yaqoob
·
Feb. 16, 17 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
15.0K Views

Join the DZone community and get the full member experience.

Join For Free

This article is intended to make you familiar with controlling VGA with x86 assembly. Yes, we don’t hear much in the field of Assembly Language programming, as it is not quite as popular as compared to other programming and web development languages such as Java, HTML, Bootstrap, or SEM. But it is essential on its own and knowledge of it proves to be quite helpful in understanding how computers work internally. Of course, you need to be familiar with x86 assembly beforehand which includes knowing the instruction set as well as concepts of registers, operations, etc.

The setup that you will need includes installing ‘dosbox’ as well as ‘EMU8086’ on your machine. Install both of them. EMU8086 is intended to compile our source code into machine code, and then we will run the compiled code inside the environment that Dosbox will provide. After you’ve installed them, open up EMU8086, create a new ‘.COM’ file, and then paste the following code inside the editor:

org 100 h

  .data

temp dw 80 dup(0);
declares an array of 80 words and initializes them with 0

  .code

mov ax, 0xb800

mov es, ax;
es register now points towards video memory

here:

  mov si, 0

mov di, 0

mov cx, 80;
counter
for copying first line of display

;
copies the first line of the display to a temp array

loop1:

  mov ax, es: si;
character from video memory to ax register

mov[temp + di], ax;
copying that character to temp array

add si, 2;
incrementing the source and destination registers

add di, 2

loop loop1

mov cx, 3840;
counter
for shifting the remaining rows to top

mov si, 0;
destination => first box

mov di, 160;
source => box right below it

;
copies each digit from source to the memory cell above it

loop2:

  mov ax, es: di

mov es: si, ax

add si, 2

add di, 2

loop loop2

mov di, 0

mov si, 3840

mov cx, 80

;
pasting the data of the top row at bottom

loop3:

  mov ax, [temp + di]

mov es: si, ax

add si, 2

add di, 2

loop loop3

jmp here


It might feel a little bit overwhelming, but you’ll understand it by the end of the article. Actually, you can run this code inside EMU8086, but the running of this program will be very tedious and there will be no content on the screen to scroll.

My approach to scrolling the screen infinitely is to do the following:

1): The screen is 80x25 => 80 columns and 25 rows.

2): Store the first row data in a temporary array.

3): Shift the data from the remaining rows to the above rows.

4): Paste the data stored in the temp array at the end row.

5): Use an unconditional jump to go back and do the same process again.

Explanation:

The VGA screen is 80 (columns) x 25 (rows) . And each memory cell is in (2-bytes) size. So we have a total of 2000 memory cells. And in terms of size, we have 4000 bytes. So the first location is at ‘0’, the last memory cell of the first row is at‘158’ (80x2) - 2 ‘ because we start with 0. The bottom left memory cell is at ‘3840’ and the bottom right memory cell is at ‘3998.’

temp dw 80 dup(0); declares an array of 80 words and initializes them with 0.

This is the temporary array declaration inside the data segment. This will declare 80-word size memory locations inside the memory and put ‘0’ in them.

mov ax, 0xb800

mov es, ax

The VGA memory is at the address: ‘0xB800’. So we put that address inside the 'ax' register and then we move that address to ‘es’ (extended segment) register. Keep in mind that we cannot copy the address directly into the ‘es’ register.

here:

mov si, 0

mov di, 0

mov cx, 80


loop1:


mov ax, es:si 

mov [temp + di], ax 

add si, 2

add di, 2


loop loop1

We move ‘0’ to SI and DI registers and initialize our counter register cx with ‘80,' because we want to extract only the first row of the temp array. ‘mov ax, es:si’ extracts the character and puts in the ax register and ‘mov [temp + di], ax’ puts that character from 'ax' into the temp array. And we increment the SI and DI register by ‘2’ (word size) to point to the next consecutive memory location. And the loop starts again until it reaches its limit, i.e. cx is equal to 0.

mov cx, 3840 ; counter for shifting the remaining rows to top

mov si, 0    ; destination => first box

mov di, 160  ; source => box right below it


; copies each digit from source to the memory cell above it


loop2:


mov ax, es:di

mov es:si, ax


add si, 2

add di, 2


loop loop2

Now we have the first row in the temp array, and we are left with 24 rows. 80x24 = 1920 (1920x2=3840) So we have 3840 in our 'cx' register now for shifting the other rows to the top one by one. SI initially points to the first memory cell, and DI points to the memory cell directly below it that reads ‘160.’ We copy the contents of the memory cell pointed by the ‘DI’ register and paste them into the SI memory cell directly above it. And then we increment both by 2. This way we will copy the content of each memory cell to the memory cell above it until we reach the last memory cell, and that is where our loop will terminate.

Now, we have to paste the data from our temp array to the last row.

mov di, 0

mov si, 3840

mov cx, 80

;
pasting the data of the top row at bottom

loop3:

  mov ax, [temp + di]

mov es: si, ax

add si, 2

add di, 2

loop loop3

jmp here

This code will do it. DI points to the first memory cell in the temp array. And SI points to the bottom left memory cell. The counter is again at 80 (the number of memory cells in a Row) and we start pasting data from temp to the VGA memory and incrementing both pointers SI and DI by 2.

Up to Now, We’ve:

1): Copied the first row to a temporary location.

2): Shifted the rest of the rows up.

3): Pasted the data from a temporary array to the last row.

That’s when the ‘jmp here’ comes into play. This fellow will jump back to the ‘here’ label inside the code and the process will start again. Copying the new top line to a top array and then shifting all the rows up, and then finally passing the data to the last row. As ‘jmp here’ is an unconditional jump so the process is infinite. And you will see the screen scrolling in DosBox.

Running:

1): Paste the code in EMU8086. Compile it, which will give us a COM file.

2): Then open DosBox. And mount the drive with the path where your.com file resides. Eg, ‘mount c: c:\emu8086\mybuild\”

3): Shift to the newly mounted drive by entering this ‘c:’

4): Run the .com file by entering its name. Eg, ‘noname.com’

Capture.PNG

And voila.

Try pressing ‘Ctrl + F11’ the cycles in the title bar become ‘1’ . That way the program execution will drastically slow down and you will notice what is happening in the execution.

Memory (storage engine) X86 assembly Row (database) Assembly (CLI) Data structure Data (computing)

Opinions expressed by DZone contributors are their own.

Related

  • Linked List in Data Structures and Algorithms
  • Troubleshooting Memory Leaks With Heap Profilers
  • Stop Running Two Data Systems for One Agent Query
  • Designing Self-Healing AI Infrastructure: The Role of Autonomous Recovery

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook