woensdag 25 april 2018
Inspect return value in Visual Studio
You can add a watch for expression $ReturnValue and that will contain the return value.
zondag 15 april 2018
vrijdag 6 april 2018
Visual Studio ideaal voor C++ / x64 assembler programming
Visual Studio is echt ideaal voor debugging C++ / x64 assembler code.
Tijdens het debuggen kun je ctrl-alt-d drukken om assembly code van de C++ code te zien.
Ook kun je de inhoud van de registers zien. Tevens van de stack, met Debug/Windows/Memory/Memory1.
In je header file van je C++ class definieer je een extern naar een assembler file als volgt:
extern "C" void RotateScreenPart(BYTE* screenSource, BYTE* screenDestination, Sint64 startY, Sint64 endY, Sint64 cosinusAngle, Sint64 sinusAngle, Sint64 centerPointX, Sint64 centerPointY, Sint64 screenWidth, Sint64 screenHeight);
Tijdens het debuggen kun je ctrl-alt-d drukken om assembly code van de C++ code te zien.
Ook kun je de inhoud van de registers zien. Tevens van de stack, met Debug/Windows/Memory/Memory1.
In je header file van je C++ class definieer je een extern naar een assembler file als volgt:
extern "C" void RotateScreenPart(BYTE* screenSource, BYTE* screenDestination, Sint64 startY, Sint64 endY, Sint64 cosinusAngle, Sint64 sinusAngle, Sint64 centerPointX, Sint64 centerPointY, Sint64 screenWidth, Sint64 screenHeight);
Vergeet niet deze typedef's op te nemen:
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef uint8_t BYTE;
typedef uint16_t Uint16;
typedef int16_t Sint16;
typedef uint32_t Uint32;
typedef int32_t Sint32;
typedef uint64_t Uint64;
typedef int64_t Sint64;
In je assembler file doe je:
RotateScreenPart proc
push rbp
mov rbp, rsp
sub rsp, 30h ; 6 qwords space.
mov [rbp-8h], r8
mov [rbp-10h], r9
mov [rbp-18h], rcx
mov [rbp-20h], rdx
push rax
mov rax, 1566 - 100
mov [rbp-28h], rax
mov rax, 1566 - 200
mov [rbp-30h], rax
push rbx
; cosinusAngle = [rbp+30h]
; sinusAngle = [rbp+38h]
; centerPointX = [rbp+40h]
; centerPointY = [rbp+48h]
; screenWidth = [rbp+50h]
pop rbx
pop rax
mov rsp, rbp
pop rbp
ret
RotateScreenPart endp
Aan de bovenstaande code zie je dat de
parameter1 = rcx
parameter2 = rdx
parameter3 = r8
parameter4 = r9
mov rax, [rbp+30h] ; parameter 5
mov rax, [rbp+38h] ; parameter 6
Je kunt ook nog lokale space aanmaken. Zie RotateScreenPart.
Visual Studio C++ resource toevoegen
Je kunt in Visual Studio C++ makkelijk een resource toevoegen, zodat je bijvoorbeeld een plaatje niet van disk hoeft te laden.
Je doet rechter muisknop -> Add.. -> Resource... -> Custom... -> RCDATA (invullen in textbox).
Vervolgens moet je bytes invullen. Je tikt wat in.
Vervolgens kijk je hoe het nieuwe bestand op schijf heet, en overschijft 'm met jouw juiste bestand.
Vervolgens kun je in C++ op de volgende manier je resource inladen:
HRSRC myResource = ::FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA2), RT_RCDATA);
unsigned int myResourceSize = ::SizeofResource(NULL, myResource);
HGLOBAL myResourceData = ::LoadResource(NULL, myResource);
void* pMyBinaryData = ::LockResource(myResourceData);
unsigned char* buffer = (unsigned char*)pMyBinaryData;
Je doet een LockResource en dan verwacht je dat je weer iets moet vrijgeven. Dat hoeft echter niet volgens bronnen op Internet.
Je doet rechter muisknop -> Add.. -> Resource... -> Custom... -> RCDATA (invullen in textbox).
Vervolgens moet je bytes invullen. Je tikt wat in.
Vervolgens kijk je hoe het nieuwe bestand op schijf heet, en overschijft 'm met jouw juiste bestand.
Vervolgens kun je in C++ op de volgende manier je resource inladen:
HRSRC myResource = ::FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA2), RT_RCDATA);
unsigned int myResourceSize = ::SizeofResource(NULL, myResource);
HGLOBAL myResourceData = ::LoadResource(NULL, myResource);
void* pMyBinaryData = ::LockResource(myResourceData);
unsigned char* buffer = (unsigned char*)pMyBinaryData;
Je doet een LockResource en dan verwacht je dat je weer iets moet vrijgeven. Dat hoeft echter niet volgens bronnen op Internet.
dinsdag 3 april 2018
Volatile C++ variables
// at the module level or somewhere else global to the function
int n;
while (n > 0) { count++; }
will be readily transformed by an optimizing compiler as
if(n > 0)
for(;;)
count++;
and this is a perfectly valid translation. Because there is nothing in the loop that can change the value of n, there is no reason to ever test it again! This optimization is an example of a loop invariant computation, and an optimizing compiler will "pull this out" of the loop.
But what if the rest of the program looked like this:
registerMyThreadFlag(&n);
while(n > 0)
{
count++;
}
and the thread used the variable registered by the registerMyThreadFlag call to set the value of the variable whose address was passed in? It would fail utterly; the loop would never exit!
Thus, the way this would have to be declared is by adding the volatile attribute to the declaration of n:
volatile int n;
This informs the compiler that it does not have the freedom to make the assumption about constancy of the value. The compiler will generate code to test the value n on every iteration through the loop, because you've explicitly told it that it is not safe to assume the value n is loop-invariant.
int n;
while (n > 0) { count++; }
will be readily transformed by an optimizing compiler as
if(n > 0)
for(;;)
count++;
and this is a perfectly valid translation. Because there is nothing in the loop that can change the value of n, there is no reason to ever test it again! This optimization is an example of a loop invariant computation, and an optimizing compiler will "pull this out" of the loop.
But what if the rest of the program looked like this:
registerMyThreadFlag(&n);
while(n > 0)
{
count++;
}
and the thread used the variable registered by the registerMyThreadFlag call to set the value of the variable whose address was passed in? It would fail utterly; the loop would never exit!
Thus, the way this would have to be declared is by adding the volatile attribute to the declaration of n:
volatile int n;
This informs the compiler that it does not have the freedom to make the assumption about constancy of the value. The compiler will generate code to test the value n on every iteration through the loop, because you've explicitly told it that it is not safe to assume the value n is loop-invariant.
Abonneren op:
Posts (Atom)