該項目的主要重點是讓人們能夠通過製作圖形來以有趣的方式學習組裝編程。該框架刪除了學習Windows GUI和Direct X編程的Burdern,並設置了所有鍋爐板,然後按照幾個說明,可以看到像素完全可以在屏幕上設置在屏幕上,而無需太多努力。另外,編寫1990年代風格的圖形效果和演示很有趣。
有一個模板演示,您可以用來創建自己的演示場景。您可以通過將代碼複製到自己的刪除目錄來將其用作示例。 * demoscenes yourdemo*所有代碼都需要進入AMD64目錄,因為這是一個X86-64彙編項目,不應使用任何C或其他Langauges 。源文件將需要修改以更改目標名稱。複製MakeFile,但您不修改Make File。要構建項目,您使用BCZ命令。您還需要更新DIRS文件,以便使用Root Directories使用BCZ構建應用程序和庫。
發動機將使用三個函數來給您回電。
發動機將使用三個函數來給您回電。
所有這些函數都傳遞了一個單個參數,該參數是Master.inc中定義的Master_Demo_struct.inc 。這包括“演示”的視頻緩衝區以及屏幕的大小以及其他一些信息。
請注意,步幅是視頻緩衝區中每條水平線的字節中的實際長度。它包括您不應該畫的隱藏部分。因此,使用寬度來計算圖紙的邊界,但使用大步計算如何到達視頻緩衝區中的下一條水平線。但是,您也可以使用雙緩衝區庫執行圖形,並使用Double Buffer API將其更新到屏幕。
有X64揮發性和非揮發性登記冊。您可以在MSDN上查看它們:https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx,每個函數調用都將在RSP對準0xffffffffffffffffffffffffffffffff8時發生。如果您打算調用任何功能,則必須將堆棧與0xffffffffffffffff0對齊,因為某些功能會假定他們可以使用需要Alignemnt(例如移動)的指令。如果堆棧不對齊,則可能會在某些較低功能調用中崩潰的風險。
X86-64中的功能調用要求堆棧中保留了4個參數位置。所有堆棧預訂都在.entprolog之前完成,以便通過跟踪堆棧中保留的空間數量來工作。前四個參數是RCX或XMM0,RDX或XMM1,R8或XMM2和R9或XMM3。在所需的4個堆棧位置保留後,無論傳遞多少個參數,都必須在堆棧上傳遞4之外的參數。當您使用寄存器傳遞這些參數時,前4個參數也沒有填充。但是,該空間可用於被調用的函數來保存參數,因為它們處於揮發性寄存器中,或者使用該空間來保存所需的一切。
Parameter N (Not Required, must be populated with Nth parameter if exists)
...
Parameter 5 (Not Required, must be populated with 5th parameter if exists)
Parameter 4 (Required, but not populated use register)
Parameter 3 (Required, but not populated use register)
Parameter 2 (Required, but not populated use register)
Parameter 1 (Required, but not populated use register)
Return Address
Save registers
Locals
Parameter Frame for Function Calls in this function.
在debug_public.inc中有兩個debug宏,第一個是debug_rsp_check_macro,如果不是構建調試,則無能為力,但是當debug構建時,您直接將其放在.end.end.end.end.end.end.end.end.end.end.clog之後,並且會檢查RSP是否對齊或INT 3。
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
您可以使用的下一個宏是debug_function_call,而不是使用呼叫指令。當不啟用調試時,此宏僅是調用的。啟用調試後,它將在您的功能調用之前保存非揮發寄存器,然後在您的函數函數調用後,它將驗證它們是正確的。然後,除了RAX/XMM0之外,它將損壞所有具有垃圾的非揮發寄存器,因為它們可以從功能中返回數據。目的是,如果您假設揮發性寄存器保留了信息,則迫使他們有望造成崩潰或錯誤,如果您這樣做。
;
; Generate new random color
;
DEBUG_FUNCTION_CALL Math_rand
以下描述了目錄結構佈局。
該框架包含各種功能,您可以通過提供基本的常規功能來加速演示構建。
dbuffer_create
dbuffer_updatescreen
dbuffer_clearbuffer
dbuffer_free
debug_is_enabled
debug_function_call
debug_rsp_check_macro
Engine_debug
frameloop_create
Frameloop_performframe
frameloop_reset
frameloop_free
SOFT3D_INIT
SOFT3D_SETCAMERAROTATION
SOFT3D_SETVIEWDISTANCE
SOFT3D_SETVIEWPOINT
SOFT3D_SETASPECTRATIO
SOFT3D_CONVERT3DTO2D
SOFT3D_CLOSE
vpal_create
VPAL_SETCOLORINDEX
vpal_getColorIndex
vpal_rotate
vpal_rotatereset
vpal_free
prm_drawcircle
prm_drawline
gameengine_init
gameengine_printword
gameengine_loadgif
gameengine_convertimagetosprite
gameengine_displayfullscreenanimatimateImage
gameengine_displayCenteredImage
gameengine_free
inputx64_registerKeypress
inputx64_registerKeyRelease
gif_open
gif_close
gif_numberofimages
gif_getImagesize
gif_getImageWidth
gif_getImageHeight
gif_getimage32bpp
gif_getimage32bpprealtime
GIF_GETALLIMAGE32BPP
以下是如何在演示中使用一些庫和框架功能的編碼示例。
調色板的創建很簡單,您只需提供顏色的數量,然後將返回地址保存為調色板手柄。
MOV RCX, 256
DEBUG_FUNCTION_CALL VPal_Create
TEST RAX, RAX
JZ @Failure_Exit
MOV [VirtualPallete], RAX
然後,您可以為每個顏色索引生成顏色。下面的示例會產生越來越多的白色調色板。如果您使用的是雙緩衝區API,則可以採用調色板的手柄並填充視頻緩衝區,並帶有適當的顏色。
@CreateWhitePalette:
MOV RAX, R12
MOV AH, AL
SHL RAX, 8
MOV AL, AH
MOV R8, RAX
MOV RDX, R12
MOV RCX, [VirtualPallete]
DEBUG_FUNCTION_CALL VPal_SetColorIndex
INC R12
CMP R12, 256
JB @CreateWhitePalette
使用以下定義的API簡單的雙緩衝區的創建非常簡單。
MOV RDX, 1 ; 1 Byte Per pixels
MOV RCX, RSI ; MASTER_DEMO_STRUCT
DEBUG_FUNCTION_CALL DBuffer_Create
MOV [DoubleBufferPointer], RAX
TEST RAX, RAX
JZ @Failure_Exit
可以根據指定的像素大小直接訪問返回的指針作為屏幕高度x寬度。
MOV RCX, [DoubleBufferPointer]
MOV BYTE PTR [RCX], 10h
然後可以通過單個功能調用更新屏幕。
;
; Update the screen with the buffer
;
MOV RCX, [DoubleBufferPointer]
MOV RDX, [VirtualPallete]
MOV R8, DB_FLAG_CLEAR_BUFFER
DEBUG_FUNCTION_CALL Dbuffer_UpdateScreen
paramhelp_public.inc中的demoscene.inc中包含宏和結構,提供了一種快速簡便的方法來設置本地堆棧框架。要記住的一件事是,如今,堆棧空間確實是免費的,因此在這個簡單的演示框架中,您不需要的堆棧空間將節省一些時間,而不是將每個堆棧專門針對所需的空間量身定制。但是,您只能保存實際計劃使用的寄存器來限制執行時間。標題文件中有宏可以通過為您提供結構和宏來保存和保存寄存器來提供幫助。如果您需要使用本地變量,則需要創建自己的其他結構,如果您只想保存一些寄存器,則可能需要手動保存這些寄存器以及宏只有距離遠處並保存所有寄存器或一些特定的寄存器。
std_function_stack_min定義為所有非揮發性通用寄存器和8個用於函數調用的參數。下面的示例顯示了使用它僅保存幾個必需的GP寄存器。
alloc_stack(SIZEOF STD_FUNCTION_STACK_MIN)
save_reg rdi, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRdi
save_reg rbx, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRbx
save_reg rsi, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRsi
save_reg r12, STD_FUNCTION_STACK_MIN.SaveRegs.SaveR12
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
... Function Code ...
MOV RSI, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRsi[RSP]
MOV RDI, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRdi[RSP]
MOV rbx, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRbx[RSP]
MOV r12, STD_FUNCTION_STACK_MIN.SaveRegs.SaveR12[RSP]
ADD RSP, SIZE STD_FUNCTION_STACK_MIN
MOV EAX, 1
RET
但是,有一個宏可以使您可以保存和還原所有GP寄存器。一個例子如下所示。
alloc_stack(SIZEOF STD_FUNCTION_STACK_MIN)
SAVE_ALL_STD_REGS STD_FUNCTION_STACK_MIN
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
... Function Code ...
RESTORE_ALL_STD_REGS STD_FUNCTION_STACK_MIN
ADD RSP, SIZE STD_FUNCTION_STACK_MIN
MOV EAX, 1
RET
下面顯示了最低限度的定義,並且總有兩個版本。第一個是當前功能的堆棧分配,第二個包括對從呼叫者傳遞給它的堆棧參數的訪問。
STD_FUNCTION_STACK_MIN struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
SaveRegs SAVE_REGISTERS_FRAME <?>
Padding dq ?
STD_FUNCTION_STACK_MIN ends
STD_FUNCTION_STACK_MIN_PARAMS struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
SaveRegs SAVE_REGISTERS_FRAME <?>
Padding dq ?
FuncParams FUNCTION_PARAMETERS_FRAME <?>
STD_FUNCTION_STACK_MIN_PARAMS ends
還有一個版本,其中包括XMM寄存器以及一個宏來保存和還原所有XMM寄存器。但是,這些標準結構都沒有局部變量。但是,如果您需要定義局部變量,則這些是可以開始的絕佳結構,然後添加您的本地變量。我將在“填充”變量為或參數和保存寄存器結構之間添加您的本地變量,如下示例所示。如果要添加本地變量,則可以使用填充位置,而無需保留。它在那裡保持對齊方式,但是您可以安排本地變量以彌補對齊問題,只需確保在保存XMM寄存器時不要陷入移動中,並使用debug_rsp_check_macro來確保保持堆棧對齊。您將需要使用debug equabled運行宏測試執行。
DEMO_FUNCTION_STACK_MIN_PARAMS struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
; Local Variables Here
SaveRegs SAVE_REGISTERS_FRAME <?>
; Or Local Variables Here
FuncParams FUNCTION_PARAMETERS_FRAME <?>
DEMO_FUNCTION_STACK_MIN_PARAMS ends