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

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Linked List in Data Structures and Algorithms
  • Troubleshooting Memory Leaks With Heap Profilers
  • How Milvus Implements Dynamic Data Update and Query
  • LLMops: The Future of AI Model Management

Trending

  • Artificial Intelligence, Real Consequences: Balancing Good vs Evil AI [Infographic]
  • Issue and Present Verifiable Credentials With Spring Boot and Android
  • Automatic Code Transformation With OpenRewrite
  • AI, ML, and Data Science: Shaping the Future of Automation
  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
14.2K 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
  • How Milvus Implements Dynamic Data Update and Query
  • LLMops: The Future of AI Model Management

Partner Resources

×

Comments

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: