Why the value of the `volatile` variable doesn't change? - c

I'm trying to understand basics of C, volatile keyword exactly.
It doesn't seem to work as I thought.
I read somewhere:
volatile specifies that value associated with the var can be modified by action
other than those in the nearby code.
When a var is declared volatile, the compiler reloads the value from
memory each time it is accessed by the program.
This prevents optimization by optimizing compilers.
It's mainly used to ensure predictable program behavior.
I've got two programs, compiled from two different .c files.
start_loop has global int variable called done with 0 as initial value and infinite loop which should test if done value have been changed to 1. Also it outputs address of the done variable to stdout.
start_loop program:
#include <stdio.h>
#include <time.h>
volatile int done = 0;
void delay(int seconds){
// some logic for time delay here
}
void main() {
while (done !=1){
delay(4);
printf("adress of `done`: %p\nvalue: %d\n", &done, done);
}
}
And change_done_var_value program which should get the address of the done variable as main argument and change it from 0 to 1.
Thus infinite loop in start_loop program should check value of done and exit the program.
change_done_var_value:
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
char *str_arg_done = argv[1];
long int done_addr = (int)strtol(str_arg_done, NULL, 16);
long int *done = (long int *)done_addr; // converting str to pointer
printf("got the address as first arg(str): %s -> address/value %p/%li\n", argv[1], done, *done);
printf("change `done` to 1?\n");
char answer = fgetc(stdin);
if (answer == 'y')
{
*done = 1;
printf("changed\nnew value: %li", *done);
}
else
{
printf("canceled\n");
}
As i've started the start_loop program in first terminal tab i got:
4 seconds delay passed
#1
adress of `done`: 0x601048
value: 0
4 seconds delay passed
#2
adress of `done`: 0x601048
value: 0
...
In the second terminal tab i started the change_done_var_value and passed 0x601048 to it:
got the address as first arg(str): 0x601048 -> adress/value 0x601048/0
change `done` to 1?
y
changed
new value: 1
But start_loop program still runs:
4 seconds delay passed
#46
adress of `done`: 0x601048
value: 0
It seems that the change_done_var_value program got the right address value cause it shows right 0 value while dereferencing pointer to done variable..
What do i need to do to make things work(to change value of done from change_done_var_value and stop the executing of thestart_loop program)?
Or it doesn't work like this..

action other than those in the nearby code
Yes; this means things that are able to modify the corresponding chunk of memory. Most often, this will be a different thread within the same program. In some very specific platform-specific circumstances, you might arrange for a variable to be in a specific location that has a special meaning to the OS (or to the hardware); for example, on an old handheld or console you could read from a virtual memory location that represents an I/O register, in order to learn what button was pressed on the keypad. By using volatile, the compiler will understand that the value has to be checked, because the hardware may have written to that memory and your program depends on knowing about the change.
On a modern desktop computer, programs have memory protection and memory space virtualization. They cannot easily look at each others' data, and will typically need some special arrangement/permission to do so. But even when it is possible, you cannot simply check on the other program's variable by using its name - the name is only meaningful to the compiler; it is not an actual part of the compiled program (although a debug-mode compilation might try to make it behave that way a little bit).

If I understand right, you try to use memory from one program in another program? "It doesn't work like this" on any modern operating system because programs (or better: "processes") are encapsulated purposefully this way that they can't access the memory of other processes without operating-system-specific interprocess communication library functions. You can read more about them and how to use them in C in a Linux-based operating system on this website:
Linux Interprocess Communications
I'm sorry that I can't elaborate further since I never used internal interprocess communication on a common Desktop Operating System yet.
There is also a more heavy-weight option to use the socket API (which generally can be used even accross a network of distinct PCs all over the world). Using the socket API is not difficult and is taught in network lecture courses in university. You then get "server" and "client" programs and you have to take care about some "primitives" which must be called in a specific order.
A common source of tutorials seems to be the Beej Guide .
This protection mechanism is called memory virtualization. It makes that every process uses its very own virtual address space which is not equal to the one of other processes. Or brief: the same addresses in different programs will lead to separate physical addresses in the real memory.
In my opinion the design mistake here is to compile two different programs to achieve the task. The usual appraoch would be to compile only one single program which uses multi-threading (that means multiple threads of execution) because multi-threading is more light-weight than interprocess communication and maybe easier to use (at least I know how to do it). For multi-threading, you can use the pthread library in Linux-based systemes which can be included into your program with the -pthread command line option when I remember correctly).
Happy coding!

Related

Two shellcodes in one program result in segfault, how can I pass shellcode as parameter to a function?

I have two questions related to C programming and shellcoding (assembly) following below.
Question 1: Can anyone provide an answer on why putting two shellcodes in one program wouldn't work? I know it's related to the memory region but I need to know the exact reason. Program is compiled using gcc with the -zexecstack and -fno-stack-protector options.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
/* if the below line is uncommmented it will result in segault */
/* unsigned char shellcode_[] = "\x01\x02<SHELLCODE>"; */
int (*ret)() = (int(*)())shellcode;
return 0;
}
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call? (I mean just STORE two shellcodes, not RUN them simultaneously, if that's possible at all).
Question 2: if the shellcode has to be passed as a parameter to a function, what would be the proper way to do it?
Pseudocode:
unsigned char shellcode[] = "\x01\x02...";
void call_shellcode(unsigned char shellcode[200]);
main()
{
call_shellcode(shellcode);
}
void call_shellcode(unsigned char shellcode[200])
{
... print/call shellcode
}
UPDATE: As there seems to be some misunderstanding to the question, this is not the ACTUAL shellcode. I do know what shellcode is and how it is generated, and how it works. I have not provided an actual shellcode within the C stub to leave it in a readable state. The value "\x01\x01" is a pseudo code to point to the idea of the question and NOT any actual contents.
Your shellcode cannot possibly work for a very simple reason: it begins with \x01\x02:
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
I'm not sure why your think your shellcode has to begin with those two bytes: it really doesn't!
Those two bytes decode to add DWORD PTR [rdx],eax (or edx if running in 32-bit mode). Since you do not have any control over the value of RDX/EDX at the time your shellcode is called, it will very likely immediately cause a segmentation fault because RDX/EDX does not contain a valid (and writable) memory address.
Changing literally anything around the shellcode, in the function or outside, could cause the compiler to choose a different register allocation that will result in RDX/EDX having a good value at runtime that doesn't result in a crash, but that'd just be a lucky coincidence. Writing and using shellcode like this is inherently undefined behavior, or at least implementation defined (fixed an operating system and compiler) so extra care must be taken.
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call?
Well, you're not really dividing anything in "different memory regions"... whether you use one array or two or ten, they are all declared on the stack and they will be close together on the stack.
If you want to jump from one to the other, that's going to be a complex task, because in general you do not know the location of a variable on the stack beforehand, so you will have to do some math calculating your current location and then the offset from one shellcode chunk to the other, ultimately performing a relative call/jump.
If shellcode has to be passed as a parameter to a function what would be the proper way to do this?
The proper way is to mmap a region of memory that is RWX, write the shellcode into it (memcpy, read from stdin, etc.) and then pass a pointer to that memory region to the function you want. You have no guarantee that a piece of global data will be put by the compiler in an executable memory region. In fact, no modern day compiler would do that, and furthermore, no modern day kernel would map such a region as executable even if the ELF is compiled with -z execstack.
In recent kernels -z execstack is only respected for the stack itself, so passing a shellcode as function argument through a variable will only work if the variable was defined on the stack.
You can't have two variables with the same name in the same scope (this part has nothing to do with what the variables are or how they are used). Simply give the second shellcode a different name.
Note I am not going to comment at all on what you are trying to do, other than that I would not think of manually created machine code as "shell code" (which I would usually think of as code intended for a command shell like bash).

C: How to change my own program in my program in runtime?

At runtime, either the assembler or machine code (which is it?) should be somewhere in RAM. Can I somehow get access to it, and read or even write to it?
This is just for educational purposes.
So, I just could compile this code. Am I really reading myself here?
#include <stdio.h>
#include <sys/mman.h>
int main() {
void *p = (void *)main;
mprotect(p, 4098, PROT_READ | PROT_WRITE | PROT_EXEC);
printf("Main: %p\n Content: %i", p, *(int *)(p+2));
unsigned int size = 16;
for (unsigned int i = 0; i < size; ++i) {
printf("%i ", *((int *)(p+i)) );
}
}
Though, if I add
*(int*)p =4;
then it's a segmentation fault.
From the answers, I could construct the following code which modifies itself during runtime:
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
void * alignptr(void * ptr, uintptr_t alignment) {
return (void *)((uintptr_t)ptr & ~(alignment - 1));
}
// pattern is a 0-terminated string
char* find(char *string, unsigned int stringLen, char *pattern) {
unsigned int iString = 0;
unsigned int iPattern;
for (unsigned int iString = 0; iString < stringLen; ++iString) {
for (iPattern = 0;
pattern[iPattern] != 0
&& string[iString+iPattern] == pattern[iPattern];
++iPattern);
if (pattern[iPattern] == 0) { return string+iString; }
}
return NULL;
}
int main() {
void *p = alignptr(main, 4096);
int result = mprotect(p, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
if (result == -1) {
printf("Error: %s\n", strerror(errno));
}
// Correct a part of THIS program directly in RAM
char programSubcode[12] = {'H','e','l','l','o',
' ','W','o','r','l','t',0};
char *programCode = (char *)main;
char *helloWorlt = find(programCode, 1024, programSubcode);
if (helloWorlt != NULL) {
helloWorlt[10] = 'd';
}
printf("Hello Worlt\n");
return 0;
}
This is amazing! Thank you all!
In principle it is possible, in practice your operating system will protect itself from your dangerous code!
Self-modifying code may have been regarded as a "neat-trick" in the days when computers had very tiny memories (in the 1950's). It later (when it was no longer necessary) came to be regarded as bad practice - resulting in code that was hard to maintain and debug.
In more modern systems (at the end of the 20th Century) it became a behaviour indicative of viruses and malware. As a consequence all modern desktop operating systems disallow modification of the code space of a program and also prevent execution of code injected into data space. Modern systems with an MMU can mark memory regions as read-only, and not-executable for example.
The simpler question of how to obtain the address of the code space - that is simple. A function pointer value for example is generally the address of the function:
int main()
{
printf( "Address of main() = %p\n", (void*)main ) ;
}
Note also that on a modern system this address will be a virtual rather then physical address.
Machine code is loaded into memory. In theory you can read and write it just like any other part of memory your program as access to.
There can be some roadblocks to doing this in practice. Modern OSes try and limit the data sections of memory to read/write operations but no execution, and machine code sections of memory to read/execute but no writing. This is to try and limit potential security vulnerabilities that come with allowing executing what ever the program feels like putting into memory (like random stuff it might pull down from the Internet).
Linux provides the mprotect system call to allow some amount of customization for memory protection. Windows provides the SetProcessDEPPolicy system call.
Edit for updated question
It looks like you're trying this on Linux, and using mprotect. The code you posted is not checking the return value from mprotect, so you don't know if the call is succeeding or failing. Here is an updated version that checks the return value:
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
void * alignptr(void * ptr, uintptr_t alignment)
{
return (void *)((uintptr_t)ptr & ~(alignment - 1));
}
int main() {
void *p = alignptr(main, 4096);
int result = mprotect(p, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
if (result == -1) {
printf("Error: %s\n", strerror(errno));
}
printf("Main: %p\n Content: %i", main, *(int *)(main+2));
unsigned int size = 16;
for (unsigned int i = 0; i < size; ++i) {
printf("%i ", *((int *)(main+i)) );
}
}
Note the changes to the length parameter passed to mprotect and the function aligning the pointer to a system page boundary. You'll need to investigate on your specific system. My system has an alignment of 4096 bytes (determined by running getconf PAGE_SIZE) and after aligning the pointer and changing the length parameter to mprotect to the page size this works, and lets you write over your pointer to main.
As others have said, this is a bad way to dynamically load code. Dynamic libraries, or plugins, are the preferred method.
On most operating systems (Linux, Windows, Android, MacOSX, etc...), a program don't execute (directly) in RAM but has its virtual address space and runs in it (stricto sensu, the code is not -always or necessarily- in RAM; you can have code which is not in RAM and which gets executed, after some page fault bring it transparently in RAM). The RAM is (directly) managed by the OS, but your process only sees its virtual address space (initialized at execve(2) time and modified with mmap(2), munmap, mprotect, mlock(2)...). Use proc(5) and try cat /proc/$$/maps in a Linux shell to understand more the virtual address space of your shell process. On Linux, you could query the virtual address space of your process by reading the /proc/self/maps file (sequentially, it is a textual pseudo-file).
Read Operating Systems: Thee Easy Pieces to learn more about OSes.
In practice, if you want to augment the code inside your program (running on some common OS) you'll better use plugins and the dynamic loading facilities. On Linux and POSIX systems you'll use dlopen(3) (which uses mmap etc...) then with dlsym(3) you'll obtain the (virtual) address of some new function and you could call it (by storing it in some function pointer of your C code).
You don't really define what a program is. I claim that a program is not only an executable, but also made of other resources (such as specific libraries, perhaps fonts or configuration files, etc...) and that is why when you install some program, quite often much more than the executable is moved or copied (look into what make install does for most free software programs even as simple as GNU coreutils). Therefore, a program (on Linux) which generates some C code (e.g. in some temporary file /tmp/genecode.c), compiles that C code into a plugin /tmp/geneplug.so (by running gcc -Wall -O -fPIC /tmp/genecode.c -o /tmp/geneplug.so), then dlopen that /tmp/geneplug.so plugin is genuinely modifying itself. And if you code in C exclusively that is a sane way of writing self-modifying programs.
Generally, your machine code sits in the code segment, and that code segment is read-only (and sometimes even execute-only; read about the NX bit). If you really want to overwrite code (and not to extend it), you'll need to use facilities (perhaps mprotect(2) on Linux) to change that permissions and enable rewriting inside the code segment.
Once some part of your code segment is writable, you could overwrite it.
Consider also some JIT-compiling libraries, such as libgccjit or asmjit (and others), to generate machine code in memory.
When you execve a new fresh executable, most of its code does not (yet) sit in RAM. But (from the point view of user code in the application) you can run it (and the kernel will transparently, but lazily, bring code pages into RAM, thru demand paging). That is what I try to explain by saying that your program run in its virtual address space (not directly in RAM). An entire book is needed to explain that further.
For example, if you have a huge executable (for simplicity, assume it is statically linked) of one gigabyte. When you start that executable (with execve) the entire gigabyte is not brought into RAM. If your program exits quickly, most of the gigabyte have not been brought into RAM and stays on the disk. Even if your program runs for a long time, but never calls a huge routine of a hundred megabyte of code, that code part (the 100Mbyte of the never used routine) won't be in RAM.
BTW, stricto sensu, self modifying code is rarely used these days (and current processors don't even handle that efficiently, e.g. because of caches and branch predictors). So in practice, you don't modify exactly your machine code (even if that would be possible).
And malware don't have to modify the currently executed code. It could (and often does) inject new code in memory and jumps somehow to it (more precisely, call it thru some function pointer). So in general you don't overwrite existing "actively used" code, you create new code elsewhere and you call it or jump to it.
If you want to create new code elsewhere in C, plugin facilities (e.g. dlopen and dlsym on Linux), or JIT libraries, are more than enough.
Notice that the mention of "changing your program" or "writing code" is very ambiguous in your question.
You might just want to extend the code of your program (and then using plugin techniques, or JIT-compilation libraries, is relevant). Notice that some programs (e.g. SBCL) are able to generate machine code at every user interaction.
You could change the existing code of your program, but then you should explain what that exactly means (what does "code" mean for you exactly ? Is it only the currently executed machine instruction or is it the entire code segment of your program?). Do you think of self-modifying code, of generating new code, of dynamic software updating?
Can I somehow get access to it, and read or even write to it?
Of course yes. You need to change protection in your virtual address space for your code (e.g. with mprotect) and then to write many bytes on some "old code" part. Why would you want to do that is a different story (and you have not explained why). I don't see any educational purposes in doing that -you are likely to crash your program quite quickly (unless you take a lot of precautions to write good enough machine code in memory).
I am a great fan of metaprogramming but I generally generate some new code and jump into it. On our current machines, I see no value in overwriting existing code. And (on Linux), my manydl.c program demonstrates that you could generate C code, compile, and dynamically link more than a million plugins (and dlopen all of them) in a single program. In practice, on current laptop or desktop computers, you can generate a lot of new code (before being concerned by limits). And C is fast enough (both in compilation time and in run time) that you could generate a thousands of C lines at every user interaction (so several times per second), compile and dynamically load it (I did that ten years ago in my defunct GCC MELT project).
If you want to overwrite executable files on disk (I see no value in doing that, it is much simpler to create fresh executables), you need to understand deeply their structure. For Linux, dive into the specifications of ELF.
In the edited question, you forgot to test against failure of mprotect. It is probably failing (because 4098 is not a power of 2 and a page multiple). So please at least code:
int c = mprotect(p, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
if (c) { perror("mprotect"); exit(EXIT_FAILURE); };
Even with the 4096 (instead of 4098) that mprotect is likely to fail with EINVAL, because main is probably not aligned to a 4K page. (Don't forget that your executable also contains crt0 code).
BTW, for educational purposes, you should add the following code near the start of your main:
char cmdbuf[80];
snprintf (cmdbuf, sizeof(cmdbuf), "/bin/cat /proc/%d/maps", (int)getpid());
fflush(NULL);
if (system(cmdbuf))
{ fprintf(stderr, "failed to run %s\n", cmdbuf); exit(EXIT_FAILURE));
and you could add a similar code chunk near the end. You might replace the snprintf format string for cmdbuf with "pmap %d".
The most straightforward and practical way to accomplish this is to use function pointers. You can declare a pointer such as:
void (*contextual_proc)(void) = default_proc;
Then call it with the syntax contextual_proc();. You can also assign a different function with the same signature to contextual_proc, say contextual_proc = proc_that_logs;, and any code that calls contextual_proc() will then (modulo thread-safety) call the new code instead.
This is a lot like self-modifying code in effect, but it is easier to understand, portable, and actually works on modern CPUs where executable memory is not writable and instructions are cached.
In C++, you would use subclasses for this; static dispatch will implement it the same way under the hood.

How to be certain that functions in my cpu emulator are not running in parallel?

I've been writing an arcade game emulator in C using SDL and have run into a weird problem with emulating systems with multiple cpus. I've got something like this:
int done = 0;
int outputDebug = 0;
FILE *fp = fopen("debug_output.txt", "w");
while (!done)
{
// Run one instruction on cpu #1
emulate(cpu1);
if (outputDebug)
fprintf(fp, "%d %d \n", cpu1->variable1, cpu1->variable2);
// Run one instruction on cpu #2
emulate(cpu2);
// pressing a key in here toggles outputDebug
checkInput();
}
Now here's what's weird...if I comment out the if statement which should have absolutely no bearing on the emulate functions, some bugs go away, and other bugs surface. If I add in some other inconsequential code, like a call to SDL_GetTicks() for example, I'll get yet a different set of bugs. I've reproduced this several times. It is always exactly the same bugs for each variation.
The conclusion I've come to is that the two calls to the emulate function must be getting run in parallel and having other code in there causes them to get out of sync to a greater or lesser degree which breaks the emulation in different ways. I'm using the GNU C compiler and not passing any optimization arguments...I tried passing -O0 even though that's the default, and everything behaves the same way.
I'm on Windows 7, using the GNU compiler as mentioned, and SDL is the only external library I'm using.
What's going on here and how do I fix it?
I'm guessing that somewhere in your emulate functions, you're referencing uninitialised memory - eg :
void somefunction(char *somearg)
{
static char *myvar;
if (somecondition) {
myvar = somearg;
}
// Now do something with myvar
If somecondition is true first time through, then myvar would be set to an address in the process' memory space.
If somecondition is subsequently false, then myvar will be left still pointing to that same address - which is still in the processes' memory space (so wouldn't necessarily cause a failure) but not what you're expecting (hence the 'bug's).
The left-over contents of that particular address in memory could well have changed depending on the calling stack - eg. it might well be pointing to an address that happened to have been used by that "fprintf" (hence one "set of bugs"). If outputDebug is false, then that memory address might last have been used by some other function (hence a different "set of bugs").
Of course, this is all speculation (since the code you've presented looks fine), but is just an example of the sort of things that could cause the symptoms you've described, and what to possibly look for.

Assigning (const char *) to function pointer executing a hex code

I found a C code that looks like this:
#include <stdio.h>
char code[] =
"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x72\x6c"
"\x64\x01\x68\x6c\x6f\x57\x6f\x68\x20\x48\x65\x6c\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7";
int main(void)
{
int (*func)();
func = (int(*)()) code;
(int)(*func)();
return 0;
}
For the given HEX CODE this program runs well and printing ("HelloWorld"). I was thinking that the HEX CODE is some machine instructions and by calling a function pointer that's pointing to that CODE we are executing that CODE.
Was my thought right? is there something to improve it?
How this HEX CODE gets generated?
Tanks for advance.
You are correct that by forcing a function pointer like this you are calling into machine instructions written as a hexadecimal string variable.
I doubt that a program like this would work on any CPU since about 2005.
On most RISC CPUs (like ARM) and on all Intel and AMD CPUs that support 64-bit, memory pages have a No Execute bit. Or in reverse an Execute bit.
On memory pages that do not have an Execute bit, the CPU will not run code. Compilers do not put variables into executable memory pages.
In order to run injected shell codes, attackers now have to use "return into libc" or function pointer overwrite attacks which set things up to call mprotect or VirtualProtect to set the execute bit on their shell code. Either that or get it injected into a executable space such as the Java, .NET, or Javascript JIT compiler uses.
Security hardened kernels will deny the ability to call mprotect. Once the program's address space is set by the dynamic library loader, it sets a security flag and no new executable pages can be created.
In order to make it always work you could assign some executable_readwrite space with malloc or the like and put the code in there and then execute it. Then there won't be any access violation faults.
void main(int argc, char** argv)
{
void* PointerToNewMemoryRegion=0;
void (*FunctionPointer) ();
PointerToNewMemoryRegion=VirtualAlloc(RandomPointer,113,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (PointerToNewMemoryRegion == NULL)
{
std::cout<<"Failed to Allocate Memory region Error code: "<<GetLastError();
return;
}
memcpy(PointerToNewMemoryRegion, code,113);
FunctionPointer = (void(*)()) PointerToNewMemoryRegion;
(void)(*FunctionPointer) ();
VirtualFree(PointerToNewMemoryRegion,113,MEM_DECOMMIT)
}
but the code never returns to my code to execute so my last line is pointless. So my code has a memory leak.
To ask this question from a "general C" point of view isn't all that meaningful.
First of all, your code has many major problems:
The literal "\xFF\xFF\xFF" equals 0xFFFFFF00, not 0x00FFFFFF as may or may not have been the intention.
What this hex code means and if it is at all meaningful, is endian-dependent and also depends on the address bus width of the given CPU.
As others have mentioned, casts between function pointers and regular pointers isn't supported or well-defined by C, the C standard lists it as a "common extension".
That being said, code like this has about one single purpose, and that is various forms of boot loaders and self-updating software used in embedded systems.
Suppose for example that you have a boot loader program that is tasked with re-programming something in the very same segment of flash memory where said program itself is executed from. That is impossible because of the way the memory hardware works. So in order to do so, you would have to execute the actual flash programming routine from RAM. Since the array of hex gibberish is stored in RAM, the program can execute from there with the function pointer trick, assuming that the C compiler has a non-standard extension that allows the cast.
As for how to generate the code, you either write it all in assembler and then translate the assembler instructions to op codes manually (very tedious). Or more likely, you write the function in C and then disassemble it and copy/paste the op codes from the disassembly.
The latter is more dangerous though, as the critical part of getting code like this to work is calling convention: you must be absolutely sure that the function stacks/unstacks things properly when it is called and when it is done, restoring the contents of any CPU registers used etc. Which may force you to write part of the function in assembler anyhow. Needless to say, the code will be completely non-portable.

Use of keep(int,int) function in TSR programming using dos.h

While studying tsr programming i have seen the use of certain code which i cannot understand..
The example cede part is(in c):
(please explain the bolded sections)
#include "dos.h"
#include"stdio.h"
void interrupt our();
void interrupt (*prev)();
char far *scr=(char far*)0xB8000000L;
int ticks;
unsigned char color;
main()
{
prev=getvect(8); // <<<<<
setvect(8,our); // <<<<<
keep(0,10000); // <<<<<
}
You would partially understand this code if you read the answer i posted to your similar question on TSR
How to write a TSR which changes case of characters
The most important things here are
Far pointer: Since 16 bit DOS used segment offset addressing scheme, your normal near pointer could not access memory beyond 64K of it's allocated segment. You have to read details to understand it.
Video memory address: This B8000000 is the address for which you need far pointer. The special thing about this address is, that starting from this location bytes (equal to the resolution of screen * 2) are copied directly into video memory.
So if you assign a character to a pointer address after indirection it will be printed on screen
Something like
char * far p = 0xB8000000;
*p = 'a'; // this would actually print a on screen at left top
Loop forward to get to the rest of the screen.
There was a c book by yashwant kanetkar which had a good deal of reference for this. I remember using it in my undergrad many years ago.
The rest of them are just indexing api's in dos.h. Why don't you go through their description and get back here if you don't understand any?
This program installs an interrupt handler. It uses interrupt number 8, the system timer interrupt. This was a common practice to use this interrupt to "continuously" do stuff on a machine running DOS.
prev=getvect(8);
This line gets the interrupt vector, that is, a pointer to a function that the system calls 18 times per second.
setvect(8,our);
This line sets the interrupt vector, that is, tells the system to call this function, instead of the old function, 18 times per second. Note that to avoid a crash, the new function must call the old function, in addition to its main purpose (which seems to be changing the case of characters).
keep(0,10000);
This line makes the program with exit code 0 (a conventional value for success) and tells DOS to leave 10000 bytes (or maybe 16-byte units? Unlikely; I don't remember) in RAM. This is unlike normal completion of program (exit(0)), where DOS marks all RAM previously occupied by the program as free.
A common cause of a crash in a TSR program is caused by the absence of keep at the end. DOS releases the memory occupied the by the code of the function our, and in the next 1/18 of a second, a random piece of code is executed.
See Int 21/AH=31h for more information.
Please note also that the parameter to keep should be calculated by manipulating some addresses, so that you don't take too much memory, and on the other hand, take enough memory to contain the code of the function our, which performs the stuff you need. The value 10000 is just an example.

Resources