이 프로젝트의 주요 초점은 사람들이 그래픽을 통해 재미있는 방식으로 어셈블리 프로그래밍을 배울 수있는 것이 었습니다. 이 프레임 워크는 학습 Windows GUI 및 직접 X 프로그래밍 및 모든 보일러 플레이트를 설정하는 Burdern을 제거하고 모든 보일러 플레이트를 설정하고 많은 노력없이 픽셀을 화면에 설정하는 것을 볼 수있는 몇 가지 지침으로지면에 닿습니다. 또한 1990 년대 스타일 그래픽 효과와 데모를 작성하는 것이 재미 있습니다.
자신만의 데모 장면을 만드는 데 사용할 수있는 템플릿 데모가 있습니다. 코드를 자신의 Demoscene 디렉토리에 복사 하여이 예제로 사용할 수 있습니다. * demoscenes Yourdemo* 모든 코드는 x86-64 어셈블리 프로젝트이므로 AMD64 디렉토리로 이동해야 합니다 . 대상 이름을 변경하려면 소스 파일을 수정해야합니다. makefile은 복사되지만 Make 파일을 수정하지 않습니다. 프로젝트를 구축하려면 BCZ 명령을 사용합니다. 루트 디렉토리에서 BCZ를 사용하여 응용 프로그램 및 라이브러리를 구축하려면 Dirs 파일을 업데이트해야합니다.
엔진이 다시 전화하는 데 사용할 세 가지 기능이 있습니다.
엔진이 게임을 위해 다시 전화하는 데 사용할 세 가지 기능이 있습니다.
이러한 모든 함수는 Master.inc 에 정의 된 Mas
보폭은 비디오 버퍼의 각 수평선의 바이트의 실제 길이입니다. 여기에는 당신이 그려서는 안되는 숨겨진 부분이 포함되어 있습니다. 따라서 너비를 사용하여 드로잉의 경계를 계산하지만 보폭을 사용하여 비디오 버퍼의 다음 수평선으로 이동하는 방법을 계산하십시오. 그러나 더블 버퍼 라이브러리를 사용하여 그래픽을 수행하고 이중 버퍼 API를 사용하여 화면으로 업데이트 할 수도 있습니다.
X64 휘발성 및 비 휘발성 레지스터가 있습니다. msdn : https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx에서도 볼 수 있으며, 각 기능 호출은 0xffffffffffffff8에 정렬 된 RSP에서 발생합니다. 함수를 호출하려는 경우 일부 함수는 Movaps와 같은 alignemnt가 필요한 지침을 사용할 수 있다고 가정하므로 스택을 0xffffffffffffffff0에 정렬해야합니다. 스택이 정렬되지 않으면 더 낮은 기능 호출에서 충돌 위험이 실행됩니다.
x86-64의 함수 호출은 스택에 4 개의 매개 변수 위치가 예약되어 있어야합니다. 모든 스택 예약은 스택에 예약 된 공간의 양을 추적하여 스택 워크가 작동 할 수 있도록 .endprolog 이전에 수행됩니다. 처음 4 개의 파라미터는 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_rsp_check_macro입니다. 디버그가 구축되지 않으면 아무것도 수행하지 않지만 디버그를 구축하면 직접 넣으면 RSP가 정렬되거나 int 3을 확인합니다.
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
다음 매크로를 사용할 수있는 매크로는 통화 명령을 사용하는 대신 Debug_Function_Call입니다. 이 매크로는 디버그가 활성화되지 않으면 단순히 호출됩니다. 디버그가 활성화되면 기능 호출 전에 비 휘발성 레지스터를 저장하면 functoin 호출 후에는 올바른지 확인합니다. 그런 다음 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
엔진 _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_displayfullscreenanimatedImage
GameEngine_displayCenteredImage
GameEngine_free
inputx64_registerkeypress
inputx64_registerkeyyRelease
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를 사용하는 경우 팔레트 핸들을 가져 와서 비디오 버퍼를 Appropraite 색상으로 채울 수 있습니다.
@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 레지스터를 저장할 때 MOVAPS에 트랩하지 않도록하고 Debug_RSP_CHECK_MACRO를 사용하여 스택 정렬이 유지되도록하십시오. 거시적 테스트 시행을 위해 Debug Equal을 사용하여 실행해야합니다.
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