Sign in to follow this  
FantasyVII

Game development with assembly. Where to start?

Recommended Posts

Hello,

 

For the past few days I have been learning assembly and I was wondering how to display graphics on the screen.

 

I'm doing this just for fun because I feel like I'm starting to burn out on my main game project and I thought I would do something fun like learn assembly. However displaying text on a console wasn't very exciting for me. So I'm taking it to the next level.

 

So, does anyone know how to start game development with assembly?

 

thanks happy.png

Share this post


Link to post
Share on other sites

...something fun like learn assembly. However displaying text on a console wasn't very exciting for me.


Writing assembly doesn't get much more exciting than that! It does get more tedious and much more difficult, however. You do graphics in the exact same way as you'd do it in C - just with more effort to manage the same data and make the same calls.

If you want to have fun with assembly, you should try reverse engineering and modifying other people's programs instead. Edited by Nypyren

Share this post


Link to post
Share on other sites

I'm not entirely sure about game dev in assembly, but I do know that rollercoaster tycoon was made in assembly except for the parts to interface with windows and directx. My guess would be that you have to do something along those lines.

 

Alternatively, make a game using ascii art?

Share this post


Link to post
Share on other sites


I'm doing this just for fun because I feel like I'm starting to burn out on my main game project and I thought I would do something fun like learn assembly. However displaying text on a console wasn't very exciting for me.

 

C/C++ is actually a perfect tool to learn assembly. You may write methods within C++ source using an assembly functions; or write assembly function is separate *.asm file and link with C++ project (need to understand well the convention to transfer parameters). The problems where writing in assembly makes a practical sense is some bit-juggling algorithms where each CPU cycle is absolutely critical to ensure max performance; once you deal with bytes/words etc... the algorithms implemented in C is often more efficient, the more complex algorithm the more advantage C code may have; modern C compilers do a marvelous job to optimize... BUT to write a performance optimal C algorithms you must have a good idea how it is translated to assembly so assembly listing of C++ code is a paramount to have during such performance-critical-development. You may gain a way more performance improving/inventing algorithms; it is a major method to make things run faster. Once algorithm is perfected you may consider to implement/optimize some tiny parts in assembly... Another area where assembly makes sense is to write some performance optimized standard calls; for example, setjump/longjump to return back to root level from a deep recursion can be times faster then standard equivalents (as soon as the compromises/limitations of such fast implementation are well understood). Anyway, writing/understanding in/assembly is really a fun and very useful (actually, it's a critical skill) to get maximum performance; but writing all project in assembly makes no practical sense... 

Share this post


Link to post
Share on other sites

Are you trying to learn asm or just take a rest from your project? If this is just for short distraction then try something completely else ( I did that and keep coming back to it, also just for fun) - write something for any of old 8 bit consoles or computers. My favourite is Atari 2600 VCS and 6502 assembler language (look for Stella emulator, it's not only emulator, it's very sophisticated and full featured debugger! If only developers could have such tool in 80s ;)). VCS is very simple in terms of architecture, but because of constraints incredibly challenging (today if feels like solving a puzzle rather than making a game;)). This will not teach you any modern assembler, but will show you basics of ANY asm. For many years rules didn't change, while knowing 6502 you will be able if not write, then at least read modern asm code. It may appear very handy during debugging mysterious issues.

Share this post


Link to post
Share on other sites

Have you considered old school game programming ie vga based game? Or homebrew development for the GBA?

Another hobby thing you could look into is SIMD coding using intrinsics.

 

That sounds very interesting. How do go about doing that?

 

 

Are you trying to learn asm or just take a rest from your project? If this is just for short distraction then try something completely else ( I did that and keep coming back to it, also just for fun) - write something for any of old 8 bit consoles or computers. My favourite is Atari 2600 VCS and 6502 assembler language (look for Stella emulator, it's not only emulator, it's very sophisticated and full featured debugger! If only developers could have such tool in 80s ;)). VCS is very simple in terms of architecture, but because of constraints incredibly challenging (today if feels like solving a puzzle rather than making a game;)). This will not teach you any modern assembler, but will show you basics of ANY asm. For many years rules didn't change, while knowing 6502 you will be able if not write, then at least read modern asm code. It may appear very handy during debugging mysterious issues.

 

At first it was just a distraction but honestly after I made few small programs in assembly I really started loving the language. I will check out Stella.

Thanks ^_^

Share this post


Link to post
Share on other sites

 


That sounds very interesting. How do go about doing that?

Which one?  Old school PC, GBA, or SSE1-4 with intrinsics?

 

ooh nvm. I found all three of those on my own happy.png

 

I do need to do more research about SSE because all i know about it, is that it's some kind of intersection set for the cpu. that's all. I'm reading about it right now.

 

Thanks.

Edited by FantasyVII

Share this post


Link to post
Share on other sites

At first it was just a distraction but honestly after I made few small programs in assembly I really started loving the language. I will check out Stella.

 

Also, if you find retro-programming interesting and inspiring I recommend to read the book "Racing the beam" smile.png Despite you can't make any commercial game any more using those old technologies, there are few things you will learn. One is very important - you will learn to treasure any given hardware resources, you will start thinking "cycles" and "memory" even including size of the generated code, and also you will be always thinking, what the compiler may do to your code during compilation. These are skills very often skipped by modern age programmers, but in video games, where every millisecond of frame counts - still valuable. That's why it's good from time to time to reach for ancient stuff, for learning, for exercise, and to remember that hardware resources are not made of rubber, they won't stretch smile.png Thinking "assembler" is valuable good thing. I worked with many programmers who, when saw a crash in place of code with no source code, couldn't do anything. Sometimes just by looking at the disassembled crash place, and understanding basics of assembler (loading, storing, moving, branching, jumping, comparing, pushing/popping, simple arithmetic, registers, memory access) you may look at actually any code and figure out what's going on there having just vague knowledge about the device low-level architecture. Those things haven't changed lot since 8-bit platforms. Sure we have more sophisticated multi-core CPUs, larger instruction sets etc. but basic principles stayed unchanged. Also hardware oriented approach keeps coming back ( like for example with PS1/PS2/PS3 ) so it's really good to know what it takes to work with directly with metal.

Edited by j_uk_dev

Share this post


Link to post
Share on other sites
Having a very old in the past introduction in my education of embeded controlers. Z80 and 6800?
Which faded away out of my head.

For modern game programming. ASM is a to low level solution C/ C++ is as low as I want to go.
If I go for ASM then it wil be for practical use of those modern CPU extentions.
Math libs using SSE2 as its very common in mainstream CPU.
But AVX AVX256 and the upcoming 512 is not. First for fun. With practical option for it.
It will be very new to me to.

Share this post


Link to post
Share on other sites
Skyscraper development with a hammer and nails. Where to start?

 

There I fixed your title for you :)

 

No, on a more serious note this is possible. I think though other replies have neglected one important point. Are you asking how to make an oldschool 256 colour game with 320x200 screen resolution and adlib sound etc? Or, are you just planning to interface modern apis using assembly and if so are you aiming for 32 or 64 Bit as I personally consider 64 Bit much more elegant. 

 

You need to look up mode 13h and vga registers, possibly Ralph brown's interrupt list, if you want to develop raw dos style graphics without relying on windows and 3d acceleration. You will also need to know how to draw your own lines and triangles. Look up bresenhams line drawing algorithm to get you started.

 

Enjoy!

Share this post


Link to post
Share on other sites

Skyscraper development with a hammer and nails. Where to start?

 

There I fixed your title for you smile.png

 

No, on a more serious note this is possible. I think though other replies have neglected one important point. Are you asking how to make an oldschool 256 colour game with 320x200 screen resolution and adlib sound etc? Or, are you just planning to interface modern apis using assembly and if so are you aiming for 32 or 64 Bit as I personally consider 64 Bit much more elegant. 

 

You need to look up mode 13h and vga registers, possibly Ralph brown's interrupt list, if you want to develop raw dos style graphics without relying on windows and 3d acceleration. You will also need to know how to draw your own lines and triangles. Look up bresenhams line drawing algorithm to get you started.

 

Enjoy!

 

 

I have actually started learning assembly using 64bit. So it would be nice to keep using that. Although I don't think there is a difference between the two other than the cpu registers name. like rax register for 64 bit vs eax register for 32bit.

 

But I have been looking into NES game development. It looks very interesting. Honestly If I can display a pixel on the screen and move it using the keyboard I would call that a success. For now I'm using ascii graphics. 

 

I will check out what you just posted. Thanks happy.png

 

 

Again I can't stress this enough. This is just for fun. I need to clear my head from C# and SharpDX and HLSL. It's annoying at times.

Share this post


Link to post
Share on other sites

Although I don't think there is a difference between the two other than the cpu registers name. like rax register for 64 bit vs eax register for 32bit.

 

The difference is more than that. X64 uses a different and nicer calling convention which avoids use of the stack for the first few parameters (something like the first 16 which covers most functions and methods).  see: https://en.m.wikipedia.org/wiki/X86_calling_conventions

 

There's lots more that just makes it a nicer environment because you have a ton node registers to avoid stashing things on stack and in memory locations,  it's a little more like RISC and easier to optimise, and more compiler friendly. Things like the massive address space support things like position independent code (PIE) and IMHO these things are awesome. 

 

If you really want a trial by fire try writing a simple 64 bit operating system... smile.png... I did, it was fun. See; https://brainbox.cc/stash/projects/RR/repos/retrorocket/browse/kernel64

 

Feel free to reuse my code... Have fun!

Edited by braindigitalis

Share this post


Link to post
Share on other sites
x64 has changed some of the memory addressing encodings to be RIP-relative, instead of having fixed displacements (and switch tables) being patched by a relocation-aware loader. I mainly deal with disassembly rather than assembly, so I'm not sure what this looks like from the writing-new-code perspective. It was a major difference in the disassembler. Edited by Nypyren

Share this post


Link to post
Share on other sites

...something fun like learn assembly. However displaying text on a console wasn't very exciting for me.


Writing assembly doesn't get much more exciting than that! It does get more tedious and much more difficult, however. You do graphics in the exact same way as you'd do it in C - just with more effort to manage the same data and make the same calls.


Pretty much. I mean... here's a simple triangle example that I wrote a while back...
http://www.gamedev.net/blog/32/entry-2254711-oh-god-it-gets-even-worse/
.586
.model flat, stdcall
option casemap :none

includelib <d3d11.lib>
includelib <d3dcompiler.lib>

@ArgRev MACRO arglist:REQ
    LOCAL txt, arg
    txt TEXTEQU <>
%   FOR arg, <arglist>
        txt CATSTR <arg>, <,>, txt
    ENDM

    txt SUBSTR  txt, 1, @SizeStr( %txt ) - 1
    txt CATSTR  <!<>, txt, <!>>
    EXITM txt
ENDM

INVOKEC    MACRO comObject, methodNumber, args:VARARG
    LOCAL txt
    IFNB <args>
%       FOR arg, @ArgRev( <args> )
            push arg
        ENDM
    ENDIF
    mov  ecx, dword ptr [comObject]
    push ecx
    mov  eax, [ecx]
    mov  edx, dword ptr [eax + methodNumber];
    call edx
ENDM

RELEASE    MACRO comObject
     LOCAL skip
     cmp  comObject, 0
     jz  skip
     INVOKEC comObject, IUnknown_Release
skip:
ENDM

DEFINEGUID          MACRO name, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11
name    DD _1
        DW _2
        DW _3
        DB _4
        DB _5
        DB _6
        DB _7
        DB _8
        DB _9
        DB _10
        DB _11
ENDM

ExitProcess                     PROTO stdcall :DWORD
MessageBoxA                     PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD
RegisterClassExA                PROTO stdcall :DWORD
GetModuleHandleA                PROTO stdcall :DWORD
DefWindowProcA                  PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD
CreateWindowExA                 PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
PostQuitMessage                 PROTO stdcall :DWORD
ShowWindow                      PROTO stdcall :DWORD, :DWORD
UpdateWindow                    PROTO stdcall :DWORD
PeekMessageA                    PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
TranslateMessage                PROTO stdcall :DWORD
DispatchMessageA                PROTO stdcall :DWORD
D3D11CreateDeviceAndSwapChain   PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
D3DCompile                      PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
D3DGetInputSignatureBlob        PROTO stdcall :DWORD, :DWORD, :DWORD

POINT                   STRUC 4
    x                      DWORD ?
    y                      DWORD ?
POINT                   ENDS

MSG                     STRUC 4
    hwnd                   DWORD ?
    message                DWORD ?
    wparam                 WORD  ?
    lparam                 DWORD ?
    time                   DWORD ?
    point                  POINT <>
MSG                     ENDS

WNDCLASSEX              STRUC 4
    cbSize                 DWORD SIZEOF(WNDCLASSEX)
    style                  DWORD CW_VREDRAW OR CW_HREDRAW OR CW_OWNDC
    lpfnWndProc            DWORD WndProc
    cbClsExtra             DWORD 0
    cbWndExtra             DWORD 0
    hInstance              DWORD ?
    hIcon                  DWORD 0
    hCursor                DWORD 0
    hbrBackground          DWORD COLOR_BACKGROUND
    lpszMenuName           DWORD 0
    lpszClassName          DWORD className
    hIconSm                DWORD 0
WNDCLASSEX              ENDS

DXGI_RATIONAL  STRUC 4
    numerator              DWORD ?
    denominator            DWORD ?
DXGI_RATIONAL           ENDS

DXGI_MODE_DESC          STRUC 4
    w                      DWORD 800
    h                      DWORD 600
    refreshRate            DXGI_RATIONAL <1, 60>
    format                 DWORD DXGI_FORMAT_R8G8B8A8_UNORM
    scanLineOrder          DWORD 0
    scaling                DWORD 0
DXGI_MODE_DESC          ENDS

DXGI_SWAP_CHAIN_DESC    STRUC 4
    bufferDesc             DXGI_MODE_DESC <>
    sampleDesc             DXGI_RATIONAL <1, 0>
    usage                  DWORD 20h OR 40h
    bufferCount            DWORD 2
    window                 DWORD ?
    windowed               DWORD 1
    swapEffect             DWORD 0
    flags                  DWORD 0
DXGI_SWAP_CHAIN_DESC    ENDS

D3D11_BUFFER_DESC       STRUC 4
    byteWidth               DWORD ?
    usage                   DWORD ?
    bindFlags               DWORD ?
    cpuAccessFlags          DWORD ?
    miscFlags               DWORD ?
    structByteStride        DWORD ?
D3D11_BUFFER_DESC       ENDS

D3D11_SUBRESOURCE_DATA  STRUC 4
    srcData                 DWORD ?
    scrap1                  DWORD 0
    scrap2                  DWORD 0
D3D11_SUBRESOURCE_DATA  ENDS

D3D11_INPUT_ELEMENT_DESC STRUC 4
    semanticName            DWORD ?
    semanticIndex           DWORD ?
    format                  DWORD ?
    slot                    DWORD ?
    byteOffset              DWORD ?
    slotClass               DWORD ?
    dataStepRate            DWORD ?
D3D11_INPUT_ELEMENT_DESC ENDS

D3D11_VIEWPORT          STRUC 4
    topLeftX                REAL4 0.0
    topLeftY                REAL4 0.0
    windowWidth             REAL4 800.0
    windowHeight            REAL4 600.0
    minDepth                REAL4 0.0
    maxDepth                REAL4 1.0
D3D11_VIEWPORT          ENDS

MB_OK                       EQU 0
SW_SHOW                     EQU 5
CW_VREDRAW                  EQU 1
CW_HREDRAW                  EQU 2
CW_OWNDC                    EQU 20h
COLOR_BACKGROUND            EQU 1
WS_OVERLAPPED               EQU 00000000h
WS_MINIMIZEBOX              EQU 00020000h
WS_MAXIMIZEBOX              EQU 00020000h
WS_SYSMENU                  EQU 00080000h
WS_THICKFRAME               EQU 00040000h
WS_CAPTION                  EQU 00C00000h
WS_OVERLAPPEDWINDOW         EQU WS_OVERLAPPED OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX OR WS_SYSMENU OR WS_THICKFRAME OR WS_CAPTION
WM_QUIT                     EQU 0012h

D3D_DRIVER_TYPE_UNKNOWN             EQU 0
D3D_DRIVER_TYPE_HARDWARE            EQU ( D3D_DRIVER_TYPE_UNKNOWN + 1 )
D3D11_CREATE_DEVICE_SINGLETHREADED  EQU 1
D3D_FEATURE_LEVEL_9_1               EQU 09100h
D3D_FEATURE_LEVEL_9_2               EQU 09200h
D3D_FEATURE_LEVEL_9_3               EQU 09300h
D3D_FEATURE_LEVEL_10_0              EQU 0a000h
D3D_FEATURE_LEVEL_10_1              EQU 0a100h
D3D_FEATURE_LEVEL_11_0              EQU 0b000h
DXGI_FORMAT_R8G8B8A8_UNORM          EQU 28
DXGI_FORMAT_R32G32B32A32_FLOAT      EQU 2
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST EQU 4

IUnknown_QueryInterface     EQU 0h
IUnknown_AddRef             EQU 4h
IUnknown_Release            EQU 8h

ID3D10Blob_GetBufferData    EQU IUnknown_Release + 4
ID3D10Blob_GetBufferSize    EQU IUnknown_Release + 8

IDXGISwapChain_GetBuffer    EQU 24h
IDXGISwapChain_Present      EQU 20h

ID3D11Device_CreateRTView   EQU 24h
ID3D11Device_CreateVS       EQU 30h
ID3D11Device_CreatePS       EQU 3Ch
ID3D11Device_CreateBuffer   EQU 0Ch
ID3D11Device_CreateLayout   EQU 2Ch

ID3D11Context_ClearRTView   EQU 0C8h
ID3D11Context_OMSetRT       EQU 84h
ID3D11Context_IASetLayout   EQU 44h
ID3D11Context_VSSetShader   EQU 2Ch
ID3D11Context_PSSetShader   EQU 24h
ID3D11Context_IASetPrimTop  EQU 60h
ID3D11Context_RSSetViewport EQU 0B0h
ID3D11Context_IASetVertBuff EQU 48h
ID3D11Context_Draw          EQU 34h

.data
msgTitle    DB "Oh shit son!", 0
regFail     DB "Failed to register window class.", 0
cwFail      DB "Failed to create window.", 0
showFail    DB "Failed to show window.", 0
updateFail  DB "Failed to update window.", 0
d3d11Fail1  DB "Failed to create D3D11 device.", 0
d3d11Fail2  DB "Failed to get back buffer from swap chain.", 0
d3d11Fail3  DB "Failed to create render target.", 0
d3d11Fail4  DB "Failed to compile pixel shader.", 0
d3d11Fail5  DB "Failed to compile vertex shader.", 0
d3d11Fail6  DB "Failed to get vertex shader layout.", 0
d3d11Fail7  DB "Failed to create vertex buffer.", 0
d3d11Fail8  DB "Failed to create input layout.", 0
d3d11Fail9  DB "Failed to create shader resource.", 0

messageIdx  DD regFail, cwFail, showFail, updateFail, d3d11Fail1, d3d11Fail2, d3d11Fail3, d3d11Fail4, d3d11Fail5, d3d11Fail6, d3d11Fail7, d3d11Fail8, d3d11Fail9

className   DB "TestClass", 0
windowTitle DB "My Window", 0
wndClass    WNDCLASSEX <>
swapDesc    DXGI_SWAP_CHAIN_DESC <>
featureLvl  DD D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3
swapChain   DD 0
device      DD 0
newFeatLvl  DD 0
context     DD 0

blackColor  DD 0, 0, 0, 0
backBuffer  DD 0
view        DD 0
DEFINEGUID  ID3D11Texture2D_GUID, 6f15aaf2h, 0d208h, 04e89h, 09ah, 0b4h, 048h, 095h, 035h, 0d3h, 04fh, 09Ch

viewport    D3D11_VIEWPORT <>

psSource    DB "struct VS_IN { float4 pos : POSITION; float4 col : COLOR; }; struct PS_IN { float4 pos : SV_POSITION; float4 col : COLOR; }; float4 PS( PS_IN input ) : SV_Target { return input.col; }", 0
psSourceLen DD $ - OFFSET psSource
psTarget    DB "ps_5_0", 0
psEntry     DB "PS", 0

vsSource    DB"struct VS_IN { float4 pos : POSITION; float4 col : COLOR; }; struct PS_IN { float4 pos : SV_POSITION; float4 col : COLOR; }; PS_IN VS( VS_IN input ) { PS_IN output = (PS_IN)0; output.pos = input.pos; output.col = input.col; return output; }", 0
vsSourceLen DD $ - OFFSET vsSource
vsTarget    DB "vs_5_0", 0
vsEntry     DB "VS", 0

vertData    REAL4 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 0.0, 1.0
            REAL4 0.5f, -0.5f, 0.5f, 1.0, 0.0, 1.0, 0.0, 1.0
            REAL4 -0.5f, -0.5f, 0.5f, 1.0, 0.0, 0.0, 1.0, 1.0

vertDesc    D3D11_BUFFER_DESC < 96, 0, 1, 0, 0, 0 >
vertSub     D3D11_SUBRESOURCE_DATA < vertData >
vertDescPos DB "POSITION", 0
vertDescCol DB "COLOR", 0
vertLayout  D3D11_INPUT_ELEMENT_DESC < OFFSET vertDescPos, 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, 0, 0 >
            D3D11_INPUT_ELEMENT_DESC < OFFSET vertDescCol, 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, 0, 0 >
vertStride  DD 32
vertOffset  DD 0

vertBuff    DD 0
inputLayout DD 0
psShader    DD 0
psBlob      DD 0
psBlobErr   DD 0
vsShader    DD 0
vsBlob      DD 0
vsBlobErr   DD 0
layoutBlob  DD 0
vsError     DD 0
blobPtr     DD 0
blobSize    DD 0

.code
WndProc  PROC stdcall hwnd:DWORD, msg:DWORD, wparam:WORD, lparam:DWORD
    cmp    msg, 2
    jnz    done
    INVOKE PostQuitMessage, 0
    xor    eax, eax
    ret
done:
    INVOKE DefWindowProcA, hwnd, msg, wparam, lparam
    ret;
WndProc  ENDP

main  PROC
    LOCAL  hwnd:DWORD
    LOCAL  hmodule:DWORD
    LOCAL  msg:MSG

    INVOKE GetModuleHandleA, 0
    mov    hmodule, eax
    mov    wndClass.hInstance, eax

    INVOKE RegisterClassExA, OFFSET wndClass
    cmp    eax, 0
    mov    eax, 0
    jz     error

    INVOKE CreateWindowExA, 0, OFFSET className, OFFSET windowTitle, WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, 0, 0, hmodule, 0
    mov    hwnd, eax
    cmp    eax, 0
    mov    eax, 1
    jz     error

    INVOKE ShowWindow, hwnd, SW_SHOW
    INVOKE UpdateWindow, hwnd
    cmp    eax, 0
    mov    eax, 3
    jz     error

    mov    eax, hwnd
    mov    swapDesc.window, eax

    INVOKE D3D11CreateDeviceAndSwapChain, 0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, OFFSET featureLvl, 4, 7, OFFSET swapDesc, OFFSET swapChain, OFFSET device, OFFSET newFeatLvl, OFFSET context
    cmp    eax, 0
    mov    eax, 4
    jnz    error

    INVOKEC swapChain, IDXGISwapChain_GetBuffer, 0, OFFSET ID3D11Texture2D_GUID, OFFSET backBuffer
    cmp    eax, 0
    mov    eax, 5
    jnz    error

    INVOKEC device, ID3D11Device_CreateRTView, dword ptr [backBuffer], 0, OFFSET view
    cmp    eax, 0
    mov    eax, 6
    jnz    error

    INVOKE D3DCompile, OFFSET psSource, psSourceLen, 0, 0, 0, OFFSET psEntry, OFFSET psTarget, 0, 0, OFFSET psBlob, OFFSET psBlobErr
    cmp    eax, 0
    mov    eax, 7
    jnz    error

    INVOKE D3DCompile, OFFSET vsSource, vsSourceLen, 0, 0, 0, OFFSET vsEntry, OFFSET vsTarget, 0, 0, OFFSET vsBlob, OFFSET vsBlobErr
    cmp    eax, 0
    mov    eax, 8
    jnz    error

    INVOKEC vsBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC vsBlob, ID3D10Blob_GetBufferSize
    mov    blobSize, eax

    INVOKE D3DGetInputSignatureBlob, blobPtr, blobSize, OFFSET layoutBlob
    cmp    eax, 0
    mov    eax, 9
    jnz    error

    INVOKEC device, ID3D11Device_CreateBuffer, OFFSET vertDesc, OFFSET vertSub, OFFSET vertBuff
    cmp    eax, 0
    mov    eax, 10
    jnz    error

    INVOKEC layoutBlob, ID3D10Blob_GetBufferSize
    mov    blobSize, eax

    INVOKEC layoutBlob, ID3D10Blob_GetBufferData

    INVOKEC device, ID3D11Device_CreateLayout, OFFSET vertLayout, 2, eax, blobSize, OFFSET inputLayout
    cmp    eax, 0
    mov    eax, 11
    jnz    error

    INVOKEC vsBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC vsBlob, ID3D10Blob_GetBufferSize

    INVOKEC device, ID3D11Device_CreateVS, blobPtr, eax, 0, OFFSET vsShader
    cmp    eax, 0
    mov    eax, 12
    jnz    error

    INVOKEC psBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC psBlob, ID3D10Blob_GetBufferSize

    INVOKEC device, ID3D11Device_CreatePS, blobPtr, eax, 0, OFFSET psShader
    cmp    eax, 0
    mov    eax, 12
    jnz    error

    RELEASE psBlob
    RELEASE vsBlob
    RELEASE layoutBlob

    INVOKEC context, ID3D11Context_OMSetRT, 1, OFFSET view, 0
    INVOKEC context, ID3D11Context_IASetLayout, inputLayout
    INVOKEC context, ID3D11Context_VSSetShader, vsShader, 0, 0
    INVOKEC context, ID3D11Context_PSSetShader, psShader, 0, 0
    INVOKEC context, ID3D11Context_IASetPrimTop, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    INVOKEC context, ID3D11Context_RSSetViewport, 1, OFFSET viewport
    INVOKEC context, ID3D11Context_IASetVertBuff, 0, 1, OFFSET vertBuff, OFFSET vertStride, OFFSET vertOffset
gameLoop:
msgLoop:
    INVOKE PeekMessageA, ADDR msg, 0, 0, 0, 1
    cmp    eax, 0
    jz     gameNext
    cmp    msg.message, WM_QUIT
    jz     done
    INVOKE TranslateMessage, ADDR msg
    INVOKE DispatchMessageA, ADDR msg
    jmp    msgLoop
gameNext:
    INVOKEC context, ID3D11Context_ClearRTView, view, OFFSET blackColor
    INVOKEC context, ID3D11Context_Draw, 3, 0
    INVOKEC swapChain, IDXGISwapChain_Present, 0, 0
    jmp    gameLoop

done:
    RELEASE view
    RELEASE backBuffer
    RELEASE swapChain
    RELEASE device
    RELEASE context
    RELEASE vsShader
    RELEASE psShader
    RELEASE inputLayout
    RELEASE vertBuff
    INVOKE ExitProcess, eax
    ret
error:
    mov    eax, messageIdx[eax*4]
    INVOKE MessageBoxA, 0, eax, ADDR msgTitle, MB_OK
    jmp done
main  ENDP
END main

Share this post


Link to post
Share on other sites

Hello,
 
For the past few days I have been learning assembly and I was wondering how to display graphics on the screen.
 
I'm doing this just for fun because I feel like I'm starting to burn out on my main game project and I thought I would do something fun like learn assembly. However displaying text on a console wasn't very exciting for me. So I'm taking it to the next level.
 
So, does anyone know how to start game development with assembly?
 
thanks happy.png


Why do you want to do this? What do you hope to gain? Yes, there is still the ability to write optimized assembly, but you can write just as optimized code and write it far quicker in a higher level language with today's compilers. I certainly recommend learning assembly, but for no other reason than to know what is going on behind the scenes. It's a step up from writing code directly in binary. It's like learning how to fix an engine to get your driver's license.

Share this post


Link to post
Share on other sites

 

 

 


Although I don't think there is a difference between the two other than the cpu registers name. like rax register for 64 bit vs eax register for 32bit.

 

The difference is more than that. X64 uses a different and nicer calling convention which avoids use of the stack for the first few parameters (something like the first 16 which covers most functions and methods).  see: https://en.m.wikipedia.org/wiki/X86_calling_conventions

 

There's lots more that just makes it a nicer environment because you have a ton node registers to avoid stashing things on stack and in memory locations,  it's a little more like RISC and easier to optimise, and more compiler friendly. Things like the massive address space support things like position independent code (PIE) and IMHO these things are awesome. 

 

If you really want a trial by fire try writing a simple 64 bit operating system... smile.png... I did, it was fun. See; https://brainbox.cc/stash/projects/RR/repos/retrorocket/browse/kernel64

 

Feel free to reuse my code... Have fun!

 

 

ooh that is so awesome. Thanks happy.png  

 

 

 

 

...something fun like learn assembly. However displaying text on a console wasn't very exciting for me.


Writing assembly doesn't get much more exciting than that! It does get more tedious and much more difficult, however. You do graphics in the exact same way as you'd do it in C - just with more effort to manage the same data and make the same calls.

 


Pretty much. I mean... here's a simple triangle example that I wrote a while back...
http://www.gamedev.net/blog/32/entry-2254711-oh-god-it-gets-even-worse/
.586
.model flat, stdcall
option casemap :none

includelib <d3d11.lib>
includelib <d3dcompiler.lib>

@ArgRev MACRO arglist:REQ
    LOCAL txt, arg
    txt TEXTEQU <>
%   FOR arg, <arglist>
        txt CATSTR <arg>, <,>, txt
    ENDM

    txt SUBSTR  txt, 1, @SizeStr( %txt ) - 1
    txt CATSTR  <!<>, txt, <!>>
    EXITM txt
ENDM

INVOKEC    MACRO comObject, methodNumber, args:VARARG
    LOCAL txt
    IFNB <args>
%       FOR arg, @ArgRev( <args> )
            push arg
        ENDM
    ENDIF
    mov  ecx, dword ptr [comObject]
    push ecx
    mov  eax, [ecx]
    mov  edx, dword ptr [eax + methodNumber];
    call edx
ENDM

RELEASE    MACRO comObject
     LOCAL skip
     cmp  comObject, 0
     jz  skip
     INVOKEC comObject, IUnknown_Release
skip:
ENDM

DEFINEGUID          MACRO name, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11
name    DD _1
        DW _2
        DW _3
        DB _4
        DB _5
        DB _6
        DB _7
        DB _8
        DB _9
        DB _10
        DB _11
ENDM

ExitProcess                     PROTO stdcall :DWORD
MessageBoxA                     PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD
RegisterClassExA                PROTO stdcall :DWORD
GetModuleHandleA                PROTO stdcall :DWORD
DefWindowProcA                  PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD
CreateWindowExA                 PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
PostQuitMessage                 PROTO stdcall :DWORD
ShowWindow                      PROTO stdcall :DWORD, :DWORD
UpdateWindow                    PROTO stdcall :DWORD
PeekMessageA                    PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
TranslateMessage                PROTO stdcall :DWORD
DispatchMessageA                PROTO stdcall :DWORD
D3D11CreateDeviceAndSwapChain   PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
D3DCompile                      PROTO stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
D3DGetInputSignatureBlob        PROTO stdcall :DWORD, :DWORD, :DWORD

POINT                   STRUC 4
    x                      DWORD ?
    y                      DWORD ?
POINT                   ENDS

MSG                     STRUC 4
    hwnd                   DWORD ?
    message                DWORD ?
    wparam                 WORD  ?
    lparam                 DWORD ?
    time                   DWORD ?
    point                  POINT <>
MSG                     ENDS

WNDCLASSEX              STRUC 4
    cbSize                 DWORD SIZEOF(WNDCLASSEX)
    style                  DWORD CW_VREDRAW OR CW_HREDRAW OR CW_OWNDC
    lpfnWndProc            DWORD WndProc
    cbClsExtra             DWORD 0
    cbWndExtra             DWORD 0
    hInstance              DWORD ?
    hIcon                  DWORD 0
    hCursor                DWORD 0
    hbrBackground          DWORD COLOR_BACKGROUND
    lpszMenuName           DWORD 0
    lpszClassName          DWORD className
    hIconSm                DWORD 0
WNDCLASSEX              ENDS

DXGI_RATIONAL  STRUC 4
    numerator              DWORD ?
    denominator            DWORD ?
DXGI_RATIONAL           ENDS

DXGI_MODE_DESC          STRUC 4
    w                      DWORD 800
    h                      DWORD 600
    refreshRate            DXGI_RATIONAL <1, 60>
    format                 DWORD DXGI_FORMAT_R8G8B8A8_UNORM
    scanLineOrder          DWORD 0
    scaling                DWORD 0
DXGI_MODE_DESC          ENDS

DXGI_SWAP_CHAIN_DESC    STRUC 4
    bufferDesc             DXGI_MODE_DESC <>
    sampleDesc             DXGI_RATIONAL <1, 0>
    usage                  DWORD 20h OR 40h
    bufferCount            DWORD 2
    window                 DWORD ?
    windowed               DWORD 1
    swapEffect             DWORD 0
    flags                  DWORD 0
DXGI_SWAP_CHAIN_DESC    ENDS

D3D11_BUFFER_DESC       STRUC 4
    byteWidth               DWORD ?
    usage                   DWORD ?
    bindFlags               DWORD ?
    cpuAccessFlags          DWORD ?
    miscFlags               DWORD ?
    structByteStride        DWORD ?
D3D11_BUFFER_DESC       ENDS

D3D11_SUBRESOURCE_DATA  STRUC 4
    srcData                 DWORD ?
    scrap1                  DWORD 0
    scrap2                  DWORD 0
D3D11_SUBRESOURCE_DATA  ENDS

D3D11_INPUT_ELEMENT_DESC STRUC 4
    semanticName            DWORD ?
    semanticIndex           DWORD ?
    format                  DWORD ?
    slot                    DWORD ?
    byteOffset              DWORD ?
    slotClass               DWORD ?
    dataStepRate            DWORD ?
D3D11_INPUT_ELEMENT_DESC ENDS

D3D11_VIEWPORT          STRUC 4
    topLeftX                REAL4 0.0
    topLeftY                REAL4 0.0
    windowWidth             REAL4 800.0
    windowHeight            REAL4 600.0
    minDepth                REAL4 0.0
    maxDepth                REAL4 1.0
D3D11_VIEWPORT          ENDS

MB_OK                       EQU 0
SW_SHOW                     EQU 5
CW_VREDRAW                  EQU 1
CW_HREDRAW                  EQU 2
CW_OWNDC                    EQU 20h
COLOR_BACKGROUND            EQU 1
WS_OVERLAPPED               EQU 00000000h
WS_MINIMIZEBOX              EQU 00020000h
WS_MAXIMIZEBOX              EQU 00020000h
WS_SYSMENU                  EQU 00080000h
WS_THICKFRAME               EQU 00040000h
WS_CAPTION                  EQU 00C00000h
WS_OVERLAPPEDWINDOW         EQU WS_OVERLAPPED OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX OR WS_SYSMENU OR WS_THICKFRAME OR WS_CAPTION
WM_QUIT                     EQU 0012h

D3D_DRIVER_TYPE_UNKNOWN             EQU 0
D3D_DRIVER_TYPE_HARDWARE            EQU ( D3D_DRIVER_TYPE_UNKNOWN + 1 )
D3D11_CREATE_DEVICE_SINGLETHREADED  EQU 1
D3D_FEATURE_LEVEL_9_1               EQU 09100h
D3D_FEATURE_LEVEL_9_2               EQU 09200h
D3D_FEATURE_LEVEL_9_3               EQU 09300h
D3D_FEATURE_LEVEL_10_0              EQU 0a000h
D3D_FEATURE_LEVEL_10_1              EQU 0a100h
D3D_FEATURE_LEVEL_11_0              EQU 0b000h
DXGI_FORMAT_R8G8B8A8_UNORM          EQU 28
DXGI_FORMAT_R32G32B32A32_FLOAT      EQU 2
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST EQU 4

IUnknown_QueryInterface     EQU 0h
IUnknown_AddRef             EQU 4h
IUnknown_Release            EQU 8h

ID3D10Blob_GetBufferData    EQU IUnknown_Release + 4
ID3D10Blob_GetBufferSize    EQU IUnknown_Release + 8

IDXGISwapChain_GetBuffer    EQU 24h
IDXGISwapChain_Present      EQU 20h

ID3D11Device_CreateRTView   EQU 24h
ID3D11Device_CreateVS       EQU 30h
ID3D11Device_CreatePS       EQU 3Ch
ID3D11Device_CreateBuffer   EQU 0Ch
ID3D11Device_CreateLayout   EQU 2Ch

ID3D11Context_ClearRTView   EQU 0C8h
ID3D11Context_OMSetRT       EQU 84h
ID3D11Context_IASetLayout   EQU 44h
ID3D11Context_VSSetShader   EQU 2Ch
ID3D11Context_PSSetShader   EQU 24h
ID3D11Context_IASetPrimTop  EQU 60h
ID3D11Context_RSSetViewport EQU 0B0h
ID3D11Context_IASetVertBuff EQU 48h
ID3D11Context_Draw          EQU 34h

.data
msgTitle    DB "Oh shit son!", 0
regFail     DB "Failed to register window class.", 0
cwFail      DB "Failed to create window.", 0
showFail    DB "Failed to show window.", 0
updateFail  DB "Failed to update window.", 0
d3d11Fail1  DB "Failed to create D3D11 device.", 0
d3d11Fail2  DB "Failed to get back buffer from swap chain.", 0
d3d11Fail3  DB "Failed to create render target.", 0
d3d11Fail4  DB "Failed to compile pixel shader.", 0
d3d11Fail5  DB "Failed to compile vertex shader.", 0
d3d11Fail6  DB "Failed to get vertex shader layout.", 0
d3d11Fail7  DB "Failed to create vertex buffer.", 0
d3d11Fail8  DB "Failed to create input layout.", 0
d3d11Fail9  DB "Failed to create shader resource.", 0

messageIdx  DD regFail, cwFail, showFail, updateFail, d3d11Fail1, d3d11Fail2, d3d11Fail3, d3d11Fail4, d3d11Fail5, d3d11Fail6, d3d11Fail7, d3d11Fail8, d3d11Fail9

className   DB "TestClass", 0
windowTitle DB "My Window", 0
wndClass    WNDCLASSEX <>
swapDesc    DXGI_SWAP_CHAIN_DESC <>
featureLvl  DD D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3
swapChain   DD 0
device      DD 0
newFeatLvl  DD 0
context     DD 0

blackColor  DD 0, 0, 0, 0
backBuffer  DD 0
view        DD 0
DEFINEGUID  ID3D11Texture2D_GUID, 6f15aaf2h, 0d208h, 04e89h, 09ah, 0b4h, 048h, 095h, 035h, 0d3h, 04fh, 09Ch

viewport    D3D11_VIEWPORT <>

psSource    DB "struct VS_IN { float4 pos : POSITION; float4 col : COLOR; }; struct PS_IN { float4 pos : SV_POSITION; float4 col : COLOR; }; float4 PS( PS_IN input ) : SV_Target { return input.col; }", 0
psSourceLen DD $ - OFFSET psSource
psTarget    DB "ps_5_0", 0
psEntry     DB "PS", 0

vsSource    DB"struct VS_IN { float4 pos : POSITION; float4 col : COLOR; }; struct PS_IN { float4 pos : SV_POSITION; float4 col : COLOR; }; PS_IN VS( VS_IN input ) { PS_IN output = (PS_IN)0; output.pos = input.pos; output.col = input.col; return output; }", 0
vsSourceLen DD $ - OFFSET vsSource
vsTarget    DB "vs_5_0", 0
vsEntry     DB "VS", 0

vertData    REAL4 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 0.0, 1.0
            REAL4 0.5f, -0.5f, 0.5f, 1.0, 0.0, 1.0, 0.0, 1.0
            REAL4 -0.5f, -0.5f, 0.5f, 1.0, 0.0, 0.0, 1.0, 1.0

vertDesc    D3D11_BUFFER_DESC < 96, 0, 1, 0, 0, 0 >
vertSub     D3D11_SUBRESOURCE_DATA < vertData >
vertDescPos DB "POSITION", 0
vertDescCol DB "COLOR", 0
vertLayout  D3D11_INPUT_ELEMENT_DESC < OFFSET vertDescPos, 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, 0, 0 >
            D3D11_INPUT_ELEMENT_DESC < OFFSET vertDescCol, 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, 0, 0 >
vertStride  DD 32
vertOffset  DD 0

vertBuff    DD 0
inputLayout DD 0
psShader    DD 0
psBlob      DD 0
psBlobErr   DD 0
vsShader    DD 0
vsBlob      DD 0
vsBlobErr   DD 0
layoutBlob  DD 0
vsError     DD 0
blobPtr     DD 0
blobSize    DD 0

.code
WndProc  PROC stdcall hwnd:DWORD, msg:DWORD, wparam:WORD, lparam:DWORD
    cmp    msg, 2
    jnz    done
    INVOKE PostQuitMessage, 0
    xor    eax, eax
    ret
done:
    INVOKE DefWindowProcA, hwnd, msg, wparam, lparam
    ret;
WndProc  ENDP

main  PROC
    LOCAL  hwnd:DWORD
    LOCAL  hmodule:DWORD
    LOCAL  msg:MSG

    INVOKE GetModuleHandleA, 0
    mov    hmodule, eax
    mov    wndClass.hInstance, eax

    INVOKE RegisterClassExA, OFFSET wndClass
    cmp    eax, 0
    mov    eax, 0
    jz     error

    INVOKE CreateWindowExA, 0, OFFSET className, OFFSET windowTitle, WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, 0, 0, hmodule, 0
    mov    hwnd, eax
    cmp    eax, 0
    mov    eax, 1
    jz     error

    INVOKE ShowWindow, hwnd, SW_SHOW
    INVOKE UpdateWindow, hwnd
    cmp    eax, 0
    mov    eax, 3
    jz     error

    mov    eax, hwnd
    mov    swapDesc.window, eax

    INVOKE D3D11CreateDeviceAndSwapChain, 0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, OFFSET featureLvl, 4, 7, OFFSET swapDesc, OFFSET swapChain, OFFSET device, OFFSET newFeatLvl, OFFSET context
    cmp    eax, 0
    mov    eax, 4
    jnz    error

    INVOKEC swapChain, IDXGISwapChain_GetBuffer, 0, OFFSET ID3D11Texture2D_GUID, OFFSET backBuffer
    cmp    eax, 0
    mov    eax, 5
    jnz    error

    INVOKEC device, ID3D11Device_CreateRTView, dword ptr [backBuffer], 0, OFFSET view
    cmp    eax, 0
    mov    eax, 6
    jnz    error

    INVOKE D3DCompile, OFFSET psSource, psSourceLen, 0, 0, 0, OFFSET psEntry, OFFSET psTarget, 0, 0, OFFSET psBlob, OFFSET psBlobErr
    cmp    eax, 0
    mov    eax, 7
    jnz    error

    INVOKE D3DCompile, OFFSET vsSource, vsSourceLen, 0, 0, 0, OFFSET vsEntry, OFFSET vsTarget, 0, 0, OFFSET vsBlob, OFFSET vsBlobErr
    cmp    eax, 0
    mov    eax, 8
    jnz    error

    INVOKEC vsBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC vsBlob, ID3D10Blob_GetBufferSize
    mov    blobSize, eax

    INVOKE D3DGetInputSignatureBlob, blobPtr, blobSize, OFFSET layoutBlob
    cmp    eax, 0
    mov    eax, 9
    jnz    error

    INVOKEC device, ID3D11Device_CreateBuffer, OFFSET vertDesc, OFFSET vertSub, OFFSET vertBuff
    cmp    eax, 0
    mov    eax, 10
    jnz    error

    INVOKEC layoutBlob, ID3D10Blob_GetBufferSize
    mov    blobSize, eax

    INVOKEC layoutBlob, ID3D10Blob_GetBufferData

    INVOKEC device, ID3D11Device_CreateLayout, OFFSET vertLayout, 2, eax, blobSize, OFFSET inputLayout
    cmp    eax, 0
    mov    eax, 11
    jnz    error

    INVOKEC vsBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC vsBlob, ID3D10Blob_GetBufferSize

    INVOKEC device, ID3D11Device_CreateVS, blobPtr, eax, 0, OFFSET vsShader
    cmp    eax, 0
    mov    eax, 12
    jnz    error

    INVOKEC psBlob, ID3D10Blob_GetBufferData
    mov    blobPtr, eax

    INVOKEC psBlob, ID3D10Blob_GetBufferSize

    INVOKEC device, ID3D11Device_CreatePS, blobPtr, eax, 0, OFFSET psShader
    cmp    eax, 0
    mov    eax, 12
    jnz    error

    RELEASE psBlob
    RELEASE vsBlob
    RELEASE layoutBlob

    INVOKEC context, ID3D11Context_OMSetRT, 1, OFFSET view, 0
    INVOKEC context, ID3D11Context_IASetLayout, inputLayout
    INVOKEC context, ID3D11Context_VSSetShader, vsShader, 0, 0
    INVOKEC context, ID3D11Context_PSSetShader, psShader, 0, 0
    INVOKEC context, ID3D11Context_IASetPrimTop, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    INVOKEC context, ID3D11Context_RSSetViewport, 1, OFFSET viewport
    INVOKEC context, ID3D11Context_IASetVertBuff, 0, 1, OFFSET vertBuff, OFFSET vertStride, OFFSET vertOffset
gameLoop:
msgLoop:
    INVOKE PeekMessageA, ADDR msg, 0, 0, 0, 1
    cmp    eax, 0
    jz     gameNext
    cmp    msg.message, WM_QUIT
    jz     done
    INVOKE TranslateMessage, ADDR msg
    INVOKE DispatchMessageA, ADDR msg
    jmp    msgLoop
gameNext:
    INVOKEC context, ID3D11Context_ClearRTView, view, OFFSET blackColor
    INVOKEC context, ID3D11Context_Draw, 3, 0
    INVOKEC swapChain, IDXGISwapChain_Present, 0, 0
    jmp    gameLoop

done:
    RELEASE view
    RELEASE backBuffer
    RELEASE swapChain
    RELEASE device
    RELEASE context
    RELEASE vsShader
    RELEASE psShader
    RELEASE inputLayout
    RELEASE vertBuff
    INVOKE ExitProcess, eax
    ret
error:
    mov    eax, messageIdx[eax*4]
    INVOKE MessageBoxA, 0, eax, ADDR msgTitle, MB_OK
    jmp done
main  ENDP
END main

 

Whao. That is so cool. Thank you for the source code. I'm defiantly going to read this. Out of curiosity, why did you write this? just for fun or did u actually use it in one of your projects?

 

 

 

Hello,
 
For the past few days I have been learning assembly and I was wondering how to display graphics on the screen.
 
I'm doing this just for fun because I feel like I'm starting to burn out on my main game project and I thought I would do something fun like learn assembly. However displaying text on a console wasn't very exciting for me. So I'm taking it to the next level.
 
So, does anyone know how to start game development with assembly?
 
thanks happy.png


Why do you want to do this? What do you hope to gain? Yes, there is still the ability to write optimized assembly, but you can write just as optimized code and write it far quicker in a higher level language with today's compilers. I certainly recommend learning assembly, but for no other reason than to know what is going on behind the scenes. It's a step up from writing code directly in binary. It's like learning how to fix an engine to get your driver's license.

 

 

it's just a fun side project. That is really it. I really don't hope to accomplish anything with this. I have been using C# on a daily bases for the past five years, and I thought doing some low level assembly coding would be awesome. 

 

 

 

I think I found a game jam called "ASM Game Jam". I think they do game development only using assembly. That is so cool. 

http://www.assembly.org/program/game-jam/

Share this post


Link to post
Share on other sites

it's just a fun side project. That is really it. I really don't hope to accomplish anything with this. I have been using C# on a daily bases for the past five years, and I thought doing some low level assembly coding would be awesome.


Then by all means, carry on! This IS a fun side project and I would recommend any programmer have at least some basic understanding of the assembly code for the processor they are developing on; A bit of advice I need to follow myself! The only assembly experience I have is Motorola 68000 assembly from my Mac programming days. Not a lot of use for that now, although I do have a MC68000 chip being delivered and will be making a development board for fun. Not knowing x86 assembly has hamstrung me when it comes to debugging. The disassembly is meaningless to me. This is a problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this