Click here to Skip to main content
14,212,594 members
Click here to Skip to main content
Tip/Trick
Posted 14 Oct 2015

Stats

8.8K views
371 downloads
1 bookmarked

Clock Frame Design Using Assembly

,
Rate this:
4.67 (3 votes)
Please Sign up or sign in to vote.
4.67 (3 votes)
14 Oct 2015     CPOL    
Here, we will design a clock frame with Assembly Language and GDI32

Introduction

This tip describes the use of GDI32 in assembly programming language. As an example project, we will create a simple graphical analog clock frame. As assembler, we will use the NASM assembler, And for drawing the graphics, we will use the Windows GDI32 library.

Why Assembly Language?

Studying and learning assembly language will give a better idea about how a program actually executes in a computer. And also, you can learn assembly language to enhance your skill on programming.

Using the Code

We know that every Windows program contains a main window. So our clock frame project also has a main window. But in this tip, I will not explain the code used for creating the main window. Instead, I will describe the GDI32 codes used in the project.

However, if you want know about how to create a Window in Assembly language, then you might want to take a look at this CodeProject article of mine:

Let's start:

To use GDI32 functions in assembly, first you have to declare the function name as an external symbol. In NASM, you can do it as follows:

extern BeginPaint
extern EndPaint
extern Rectangle

; More functions
;.................
;.........

Now, you can use those GDI32 functions to draw what you want.

Since all drawings are done on WM_PAINT message or event, we will handle the WM_PAINT message to draw our clock frame. We will handle the message inside the main Window Procedure function. The name of the main window procedure function is WindowProc.

The following codes handle the WM_PAINT message to draw our clock frame in main window:

; case WM_PAINT
cmp dword[ebp+12], WM_PAINT
jne L2 ; Look for next message
;{     begin WM_PAINT

In the above codes, CMP instruction compares the Message parameter of WindowProc function with WM_PAINT constant and stores the result in CPU_FLAGS. If the comparison result is not equal, then JNE instruction will skip our drawing codes since our window doesn't want to paint anything.

Let's begin to write drawing codes.

GDI32 drawing begins through calling BeginPaint function:

mov  ebx,  dword[ebp+8] ; hWnd              
push dword PaintSt                     ; Pass pointer of instance to PAINTSTRUCT
push dword ebx                             ; Pass the window handle 
call BeginPaint                           ; Update area set by previous API CALL
mov dword[WindowDC], eax
; -----------------------------------

The BeginPaint function returns device context handle of window. We have stored the result into the WindowDC variable. We will use this variable many times to do various drawing operations.

Note that WindowDC is a variable declared in the .data section and PaintSt is also a variable declared in .bss section.

Now, we will call a user-defined function named FillBackground to fill the background of the window with pink color:

call FillBackground

The FillBackground function creates a pink color Pen and a pink color Brush. Then it draws a fill rectangle using Rectangle function of GDI32:

Since our background color will be pink, so create a pink pen:

RGB 255, 184, 211
push eax ; Value for color
push 2    ; Pen width
push 0     ; 0 is PS_SOLID
call CreatePen
mov dword[ebp-12], eax ; Here we need a local variable at offset 12

In the above codes, we create a pen via calling CreatePen function of GDI32 and we store the pen object handle to the local stack.

Select the pen object with Window DC through calling SelectObject function. The SelectObject function selects a GDI object into a specified device context:

push dword[ebp-12]
push dword[WindowDC]
call SelectObject

We need a pink brush that will fill our background:

RGB 255, 184, 211
push eax ; Value for color
call CreateSolidBrush
mov dword[ebp-8], eax ; Here we need a local variable at offset 8

Select the brush with Window DC:

push dword[ebp-8]
push dword[WindowDC]
call SelectObject

Now draw a rectangle and delete the pen and brush from memory:

push 382
push 382
push 0
push 0
push dword[WindowDC]
call Rectangle

; delete the brush
push dword[ebp-8]
call DeleteObject

; delete the pen
push dword[ebp-12]
call DeleteObject

Here, we will draw two ellipses as our clock frame and will create a Pen and a Brush for giving color to ellipses:

; Create a pen
RGB 0, 128, 128
push eax ; Return value of RGB macro
push 2    ; Pen width
push 0     ; 0 is PS_SOLID
call CreatePen
mov dword[ebp-12], eax ; Here we need a local variable at offset 12
; . . . . . . .  .        . ..      ..

; Create a brush
RGB 0, 166, 166
push eax ; Return value of RGB macro
call CreateSolidBrush
mov dword[ebp-8], eax ; Here we need a local variable at offset 8
; . . .  . .      ..          ...

In the above codes, a user-defined macro called RGB is used for calculating the rgb value.

; Now draw the ellipse
push 310
push 310
push 40
push 40
push dword[WindowDC]
call Ellipse

; Create pen and brush with different colors
; . . . . . .
;  . . ...

; And draw another ellipse
push 300
push 300
push 50
push 50
push dword[WindowDC]
call Ellipse

Now, we will call a user-defined function named DrawDigits to draw digit-numbers of our clock frame.

call DrawDigits

The DrawDigits function uses DrawTextA function of GDI32 to draw text and SetTextColor function of GDI32 to set color of text.

And finally, we draw our clock hands using GDI32 MoveToEx and LineTo functions.

First, we draw the hour hand of the clock:

push 0
push 175
push 175
push dword[WindowDC]
call MoveToEx

push 115
push 175
push dword[WindowDC]
call LineTo

Then we draw the minute hand:

push 0
push 175
push 175
push dword[WindowDC]
call MoveToEx

push 175
push 260
push dword[WindowDC]
call LineTo

And at last, we draw the second hand:

push 0
push 155
push 190
push dword[WindowDC]
call MoveToEx

push 250
push 120
push dword[WindowDC]
call LineTo

GDI32 drawing ends through calling EndPaint function:

; ------------------------------
mov  ebx,  dword[ebp+8] ; hWnd      
push DWORD PaintSt                 ; PAINTSTRUCT 
push DWORD ebx                     ; Window handle
call EndPaint                    ; End the paint operation  

;}     end WM_PAINT

Conclusion

I hope this tip has given you knowledge on graphics programming in assembly language.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Forhad Reza
Software Developer
Bangladesh Bangladesh
আমি একজন লেখক। নিয়মিত বিজ্ঞান বিষয়ে লিখছি। আমি সবসময় এই আশঙ্কায় থাকি যে কখন একজন লেখক ও লেখকের পরিবারের সদস্যদের ওপর বিনাদোষে অনাকাঙ্ক্ষিত দুঃখজনক পরিস্থিতি এসে পড়ে।

I'm a Bangladeshi and a citizen of Bangladesh living in Dhaka. I'm 18 years old and I've lots of experiences on computer programming. Followings are my current skills:

- Kernel (Windows & Linux) research (which is the heart of any operating system).
- Compiler design and implement.
- Expert in C, C++ and Visual Basic.
- I've the knowledge and basic experience on some other languages such as C#, D, Java etc.
- I believe I'm also good in F# language.
- Database programming.
- The world toughest programming language called Assembly, I can use it very easily.
- Working with Mozilla’s Rust & Google’s GO programming language for software development.
- Code optimization for performance.
- Multi-threaded programming in C/C++ and Java.
- Know various advanced computer algorithm and have used them to develop graphics and simulation programs. Also working with Linear Algebra and keen to learn Quadratic Algebra in future.
- Graphics and Game programming (Both 2D and 3D).

Currently, I'm doing researches on compiler and programming language development. I've made various kind of software and now I want to share my experience with people.

I love my country very much and I love all the peoples of my country. In fact, I love all the peoples live in this world. I love my country's independence. Since I'm becoming a writer, I feel insecure due to the fact that there are a lot of fake blames that are given to writers when they are totally innocent. It will happen as well as with their family.

Despite this bad situation, I'm proud of being Bengali and a Bangladeshi writer. I'm trying to take steps towards working on Computer Programming and also on Scientific subjects for my country. But it is too far from being a success and will require a lot of time due to my family's economic position.

Comments and Discussions

 
-- There are no messages in this forum --
Layout: fixed | fluid

Article Copyright 2015 by Forhad Reza
Everything else Copyright © CodeProject, 1999-2019

Server Web01
Version 2.8.190619.2