Category: Source code

How to view disassembled C/C++ code in Visual Studio Code

How to view disassembled C/C++ code in Visual Studio Code

Disassembled C source codeThere are four steps to do this. That’s assuming that you have successfully compiled your C or C++ program and have the source file handy.

  1. Install Disassembly Explorer extension into Visual Studio Code.
  2. Set a configuration setting.
  3. Run a single line command in terminal.
  4. Select a command in the Visual Studio Code command palette.

Install Disassembly Explorer.

In Visual Studio Code just switch to the extension tab and search for Dissassembly Explorer and click the install button.

Disassembly Explorer

 

 

 

Next is configuration

View the installed extensions and click the cogwheel for Disassembly Explorer then click Extension Settings at the bottom of the popup menu. A Settings tab will open, click Edit in settings.json.

You should see a few settings but only this one matters: “compilerexplorer.compilationDirectory”: “${workspaceFolder}/.vscode” . That path is where the compile etc. .json files are located.

Now open a terminal

I’ve assumed that you are running on Linux or Mac. If you are on Windows, you can also use Visual Studio Community Edition which includes disassembly features and why I’m not mentioning it here.

In the folder with your source files issue this command in the terminal.

clang -g -o asteroids.S -S asteroids.c

If OTOH you are running gcc then just substitute gcc for clang.

Finally, back in Visual Studio Code select your source file as the open tab then press F1 and in the menu that appears type in enough of Disassembly Explorer: Show until you can select it and a second tab should open with the disassembly. Click on a function in the source tab and it will jump to the correct place in the disassembled code.

And the bug is fixed

And the bug is fixed

Showing the comparison of two sources and tracking a bug downHow did I fix it? Did I spend hours debugging, poring over every line? No. I woke up in the middle of the night and thought about it and remembered that

I’d had a similar bug in this chapter when working on the original Ebook.

Stupidly I’d put the fix in the sources for the next chapter (44) but hadn’t applied it to the sources in the chapter where it had occurred (42). So I fired up my favourite code comparison tool (Devart Code Compare) and looked for differences between the source files for each chapter.

This was in the function AddObjectToCells and is part of the collision detection. It’s when an asteroid or player ship is partly on screen and calculating the cell coordinates that the object lies over. The fix was just adding these two lines so it doesn’t try and access the cells array with negative indices.

if (cellx < 0) cellx = 0;
if (celly < 0) celly = 0;
Another Windows vs Linux Difference

Another Windows vs Linux Difference

Bytes
Image From Wikimedia Commons

Once I reached the masks section in chapter 38, I found my C code that I’d copied from Windows failed because of the type byte. MSVC is a little bit more forgiving over somethings and one of those is the byte type which it accepts.  In the Windows code, I had declared the mask arrays like this:

byte bulletmask[1][3][3];
byte plmask[24][64][64];
byte a1mask[24][280][280];
byte a2mask[24][140][140]; 
byte a3mask[24][70][70];
byte a4mask[24][35][35];

But Clang in its wisdom barfed at that, not recognising the type byte. A simple fix was replace byte with char and all was well.

Looking into it, I loaded one of the Windows asteroids projects, built it and then did a ctrl-click on the byte type. It led me to a file called rpcndr.h in a Windows SDK folder and this line (191) of code.

typedef unsigned char byte;

It just shows!  My er bad…

Another new page – C Code links

Another new page – C Code links

I’ve added a page (you can see it in the bar just below the banner) for C Code links.  Just because the primary aim of this blog is about Learning C Games (programming), that includes learning C and there’s often no better way than studying or using other people’s source code.

As I come across code, I’ll add it here. I’ve started it off with Awesome-C which is a very comprehensive set of open source links.

 

Comparing MSVC vs Clang

Comparing MSVC vs Clang

Listing of some C codeI originally created Asteroids for Windows using Visual Studio 2017 Community Edition. Since then I’ve started the Clang version on Ubuntu and there haven’t been too many differences but there are just a few so in this post I’ll list what I’ve found so far.

Include Paths

On Windows, I was able to get away with #include <SDL.h> but on Linux, I’ve had to include the path so it’s #include <SDL2/SDL.h>. This was probably because I included the full path in the MSVC configuration.

Link Failures

The asteroids.c code in chapter 29 uses sin and cos for the first time and the linker was unhappy with that. So in tasks.json, I’ve explicitly had to add it into args, along with SDL2 and SDL2_image,

            "args": [
                "-g",
                "${file}","${workspaceFolder}/Asteroids/hr_time.c",
                "-o",
                "${fileDirname}/asteroids",                
                "-lSDL2",
                "-lSDL2_image",
                "-lm"
            ],

That “-lm” does that for maths.

Safe functions

Microsoft has its own set of safe functions many with an _s and extra length parameter.

On Linux, there don’t seem to be so many.

So sprintf_s on Windows becomes snprintf.

fopen_s just becomes standard fopen

linux/time.h

As well as time.h in the includes, I needed to add linux/time.h as well.

Using rsyslog to log

Using rsyslog to log

logging
Image by OpenClipart-Vectors from Pixabay

I’m a great fan of logging; it helps you find out what’s happening in a program even if you can’t debug it. Linux, well Ubuntu has a service (sorry Daemon!)  called rsyslog that logs messages from all sorts of processes and it’s quite easy to use in our programs as well.

If we don’t do the next steps all the log messages will go into a file called syslog in /var/log and as this gets a lot of stuff it can grow reasonably quickly. But if you do the following steps, all logged output will instead go into

/var/log/asteroids.log.

From a terminal type the following command:

sudo gedit /etc/rsyslog.d/30-debugging.conf

Type this in and then save it (click the Save button) and close gedit.

if $programname == 'asteroids' then /var/log/asteroids.log
& ~

Now run this command:

sudo service rsyslog restart

It should return immediately and means that any logging to syslog from a program called asteroids will from now on be redirected to /var/log/asteroids.log.

Using rsyslog in a C program

Here’s a short C Program that puts a message in the asteroids file.

#include <syslog.h>
#include <stdio.h>

int main() {
    openlog("asteroids",LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);    
    syslog(LOG_INFO,"Test Message %d",1);
    closelog();
}

In a typical program you’d put the openlog statement in main() near the start and the closelog() near the end of main, and uses as many syslog() calls throughout your program as you need.

Now what I suggest you do is open another terminal and run this command before you run your main program. This will just sit there printing out each message line as it appears in asteroids.log. You can stop tail by hitting ctrl-c.

tail -f /var/log/asteroids.log

H/T to this StackExchange answer from almost 8 years ago and answer by giuspen.

Linux E-book Progress

Linux E-book Progress

Screenshot of the chapter 28 executableMy Linux rewrite continues with progress as far as chapter 38.

This is the first Linux version of asteroids on the left and is a demo of the text writing routines and also loading images from files.

It;s drawing all digits from 0 to 99 at random locations on the screen every frame.

The number at the top is how long it takes to output the text. That value if you can’t read it is 0.000622, which means it takes 622 microseconds to output 100 numbers or 6.22 micro-seconds each.

This is the routine that does that.

void RenderEveryThing() {
	int atX, atY;

	renderTexture(textures[PLBACKDROP], 0, 0);
	startTimer(&s);
	for (int i=0;i<100;i++) {
		atX = Random(WIDTH-50) + 1;
		atY = Random(HEIGHT) + 20;
		TextAt(atX, atY, SDL_ltoa(i,buffer,10));
	}	
	stopTimer(&s);
	SDL_RenderPresent(renderer);
	frameCount++;
	UpdateCaption();
}

The most recent uploaded code version (chapter 37) lets you move the player’s ship around (press q, w or ctrl) , fire bullets (space bar), press a to see random asteroids rotating and moving round (and off) the screen. Press the b key to blow up a few asteroids with explosions and sounds. Enjoy!

Zipped up source code, graphics etc from the forthcoming Linux book can be downloaded from Github.

More on function pointers

More on function pointers

A function pointer is a pointer to a function, i.e. it’s a variable (a pointer) but instead of pointing to some data, it is assigned to a function. Most importantly, the compiler checks that the function you are assigning is compatible to that pointer. This is so, as I discussed earlier that when the function is executed, it correctly retrieves any parameters.

Here’s how you create a function pointer. Let’s start with a function that adds 1 to the input value.

int getValue(int x) {
    return n + 1;
};

This passes in x and returns an int. Let’s create a pointer to this function and this is the full program.


#include <stdio.h>

int getValue(int n) {
    return n + 1;
}

typedef int (*getValueFn)(int);

int main()
{
    getValueFn f = &getValue;
    printf( "Value of getValue = %d\n",f(1));
}

It’s as simple as that. The complicated bit is turning the function signature into the typedef. Start with the function name. Put it in brackets and add a * at the start, and make the name different to the function you are assigning. It’s a new type. So getValue becomes (*getValueFn).

Now add on the return type at the start int and the parameters at the end (int n), but throw away the name n, we only need the type and you get int (*getValueFn)(int);

Finally add typedef, cook for 30 microseconds and you’re done! In the line getValueFn f = &getValue;
I’ve declared an instance of the type f and assigned to it the address of getValue. That gets called with a value f(1) and in this case returns 2.

It’s also good practice to check that the instance variable is not null before you call it.

Function pointers in C

Function pointers in C

The one thing worse for beginners than pointers is … function pointers. A normal pointer holds the address of another variable whereas a function pointer holds the address of some code.

But before I delve into the complexities of function pointers, you have to understand a little bit about functions. A function is defined, not just by what it does but the values you pass in and get back from it. Here are a couple of examples.

int add(int b,int c) {
  return a + b;
}

void DoSomething(int value) {
  //
}

The code generated by the compiler has to pass in the parameters and usually does it by pushing values on the stack or in registers. In the code for the function, the first thing it does it fetch the parameters. So when you use a function pointer, according to the definition of that function pointer, the compiler will generate code in the function to extract parameters.

I’ll look at the syntax of function pointers tomorrow; it’s always the complicated bit, probably the most complicated bit but it dos give your program a bit more flexibility.

I’m now using the Prismatic plugin. Much nicer listing with indentations!

Using recursive fill to count maps

Using recursive fill to count maps

Terrain hexagonsIn the Empire game (yes, just one last mention!) during the map generation the program counts up the size of individual islands and sea areas. This is don by recursion and quite useful. Otherwise, the usual place you see recursion mentioned is in calculating factorials and Fibonacci sequences.

The map struct holds not only the terrain type and other information but a continent number. This is set initially to 0.  After the land and seas have been generated, the program picks a random land point on the map (just keep picking a random location until it has land with a continent number of 0).

It then counts by calling itself 8 times. It calls itself recursively at location y,x with directions (y-1,x-1) that’s NorthWest, (y-1,x)  and so on round to West (y,x-1).  But it only does it as long as each of those locations is land type with a continent number of 0. And as it does it, it sets the continent numbers in each location to 1 for the first continent and so on.

This recursive algorithm means that every contiguous land location gets reached. A similar thing is done with seas and lakes but you have to be careful that the stack is large enough.

void FillIn(int x,int y,int locis) {
  if onMap(x,y) {
    if (locis==map[x][y].locis && map[x] 
 [y].continent==UNALLOCATED) { 
      map[x][y].continent=numconts;
      allconts[numconts].count++;
      FillIn(x-1,y,locis);
      FillIn(x+1,y,locis);
      FillIn(x,y-1,locis);
      FillIn(x,y+1,locis);
      FillIn(x-1,y-1,locis);
      FillIn(x+1,y-1,locis);
      FillIn(x+1,y+1,locis);
      FillIn(x-1,y+1,locis);
    }
  }
}

This is used for both land and sea, so locis can be either. It’s an efficient algorithm and quite quick.

Those graphics? They were the initial hexagon graphics…