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.
Related
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!
Using gcc-arm-none-eabi-5_42016q3-20160926 tool chain in eclipse.
Processor: STM32F030
I have a 3 line program that starts before any hardware initializations to isolate the problem:
int a;
char * num="3";
memset(0x20000970,0XAA, 0x20001f00-0x20000970);
sscanf(num, "%i",&a);
I have set the RAM to 0XAA so I can see what gets clobbered, leaving plenty of room for the stack.
After the memset instruction the stack pointer is at 0X20001F78, the memory is 0XAA up to 0X20001F00 as expected. After I execute the sscanf function the stack pointer is back at 0X20001F78 however memory was clobbered all the way down to 0X20001BB4 which makes me think that either this simple call took almost 1K of stack or there is some other error in the routine. I have stopped using this function but am curious whether this is expected behavior? Also, is there a list of C functions that one should avoid in embedded systems, this was a surprise to me but from searching I see I am not alone.
i have the following code:
void print(const char* str){
system_call(4,1,str,strlen(str)); }
void foo2(void){ print("goo \n");}
void buz(void){ ...}
int main(){
char buf[256];
void (*func_ptr)(void)=(void(*)(void))buf;
memcpy(buf,foo2, ((void*)buz)-((void*)foo2));
func_ptr();
return 0;
}
the question is, why will this code fall?
the answer was, something about calling a function not via pointer is to a relative address, but i havent been able to figure out whats wrong here? which line is the problematic one?
thank you for your help
Well to begin with, there is nothing which says that foo2() and buz() must be next to each other in memory. And for another, as you guess, the code must be relative for stunts like that to work. But most of all, it is not allowed by the standard.
As Chris Luts referred to, stack (auto) variables are not executable on many operating systems, to protect from attacks.
The first two lines in your main() function are problematic.
Line 1. (void(*)(void))buf
converting buf to a function pointer is undefined
Line 2. ((void*)buz)-((void*)foo2)
subtraction of pointers is undefined unless the pointers point within the same array.
Also, Section 5.8 Functions of H&S says "Although a pointer to a function is often assumed to be the address of the function's code in memory, on some computers a function pointer actually points to a block of information needed to invoke the function."
First and foremost, C function pointers mechanism is for equal-signature function calling abstraction. This is powerful and error-prone enough without these stunts.
I can't see an advantage/sense in trying to copying code from one place to another. As some have commented, it's not easy to tell the amount of relativeness/rellocatable code within a C function.
You tried copying the code of a function onto a data memory region. Some microcontrollers would just told you "Buzz off!". On machine architectures that have data/program separated memories, given a very understanding compiler (or one that recognizes data/code modifiers/attributes), it would compile to the specific Code-Data Move instructions. It seams it would work... However, even in data/code separated memory archs, data-memory instruction execution is not possible.
On the other hand, in "normal" data/code shared memory PCs, likely it would also not work because data/code segments are declared (by the loader) on the MMU of the processor. Depending on the processor and OS, attempts to run code on data segments, is a segmentation fault.
I know this is more "heavy" question, but I think its interesting too. It was part of my previous questions about compiler functions, but back than I explained it very badly, and many answered just my first question, so ther it is:
So, if my knowledge is correct, modern Windows systems use paging as a way to switch tasks and secure that each task has propriate place in memory. So, every process gets its own place starting from 0.
When multitasking goes into effect, Kernel has to save all important registers to the task´s stack i believe than save the current stack pointer, change page entry to switch to another proces´s physical adress space, load new process stack pointer, pop saved registers and continue by call to poped instruction pointer adress.
Becouse of this nice feature (paging) every process thinks it has nice flat memory within reach. So, there is no far jumps, far pointers, memory segment or data segment. All is nice and linear.
But, when there is no more segmentation for the process, why does still compilers create variables on the stack, or when global directly in other memory space, than directly in program code?
Let me give an example, I have a C code:int a=10;
which gets translated into (Intel syntax):mov [position of a],#10
But than, you actually ocupy more bytes in RAM than needed. Becouse, first few bytes takes the actuall instruction, and after that instruction is done, there is new byte containing the value 10.
Why, instead of this, when there is no need to switch any segment (thus slowing the process speed) isn´t just a value of 10 coded directly into program like this:
xor eax,eax //just some instruction
10 //the value iserted to the program
call end //just some instruction
Becouse compiler know the exact position of every instruction, when operating with that variable, it would just use it´s adress.
I know, that const variables do this, but they are not really variables, when you cannot change them.
I hope I eplained my question well, but I am still learning English, so forgive my sytactical and even semantical errors.
EDIT:
I have read your answers, and it seems that based on those I can modify my question:
So, someone told here that global variable is actually that piece of values attached directly into program, I mean, when variable is global, is it atached to the end of program, or just created like the local one at the time of execution, but instead of on stack on heap directly?
If the first case - attached to the program itself, why is there even existence of local variables? I know, you will tell me becouse of recursion, but that is not the case. When you call function, you can push any memory space on stack, so there is no program there.
I hope you do understand me, there always is ineficient use of memory, when some value (even 0) is created on stack from some instruction, becouse you need space in program for that instruction and than for the actual var. Like so: push #5 //instruction that says to create local variable with integer 5
And than this instruction just makes number 5 to be on stack. Please help me, I really want to know why its this way. Thanks.
Consider:
local variables may have more than one simultaneous existence if a routine is called recursively (even indirectly in, say, a recursive decent parser) or from more than one thread, and these cases occur in the same memory context
marking the program memory non-writable and the stack+heap as non-executable is a small but useful defense against certain classes of attacks (stack smashing...) and is used by some OSs (I don't know if windows does this, however)
Your proposal doesn't allow for either of these cases.
So, there is no far jumps, far pointers, memory segment or data segment. All is nice and linear.
Yes and no. Different program segments have different purposes - despite the fact that they reside within flat virtual memory. E.g. data segment is readable and writable, but you can't execute data. Code segment is readable and executable, but you can't write into it.
why does still compilers create variables on the stack, [...] than directly in program code?
Simple.
Code segment isn't writable. For safety reasons first. Second,
most CPUs do not like to have code segment being written into as it
breaks many existing optimization used to accelerate execution.
State of the function has to be private to the function due to
things like recursion and multi-threading.
isn´t just a value of 10 coded directly into program like this
Modern CPUs prefetch instructions to allow things like parallel execution and out-of-order execution. Putting the garbage (to CPU that is the garbage) into the code segment would simply diminish (or flat out cancel) the effect of the techniques. And they are responsible for the lion share of the performance gains CPUs had showed in the past decade.
when there is no need to switch any segment
So if there is no overhead of switching segment, why then put that into the code segment? There are no problems to keep it in data segment.
Especially in case of read-only data segment, it makes sense to put all read-only data of the program into one place - since it can be shared by all instances of the running application, saving physical RAM.
Becouse compiler know the exact position of every instruction, when operating with that variable, it would just use it´s adress.
No, not really. Most of the code is relocatable or position independent. The code is patched with real memory addresses when OS loads it into the memory. Actually special techniques are used to actually avoid patching the code so that the code segment too could be shared by all running application instances.
The ABI is responsible for defining how and what compiler and linker supposed to do for program to be executable by the complying OS. I haven't seen the Windows ABI, but the ABIs used by Linux are easy to find: search for "AMD64 ABI". Even reading the Linux ABI might answer some of your questions.
What you are talking about is optimization, and that is the compiler's business. If nothing ever changes that value, and the compiler can figure that out, then the compiler is perfectly free to do just what you say (unless a is declared volatile).
Now if you are saying that you are seeing that the compiler isn't doing that, and you think it should, you'd have to talk to your compiler writer. If you are using VisualStudio, their address is One Microsoft Way, Redmond WA. Good luck knocking on doors there. :-)
Why isn´t just a value of 10 coded directly into program like this:
xor eax,eax //just some instruction
10 //the value iserted to the program
call end //just some instruction
That is how global variables are stored. However, instead of being stuck in the middle of executable code (which is messy, and not even possible nowadays), they are stored just after the program code in memory (in Windows and Linux, at least), in what's called the .data section.
When it can, the compiler will move variables to the .data section to optimize performance. However, there are several reasons it might not:
Some variables cannot be made global, including instance variables for a class, parameters passed into a function (obviously), and variables used in recursive functions.
The variable still exists in memory somewhere, and still must have code to access it. Thus, memory usage will not change. In fact, on the x86 ("Intel"), according to this page the instruction to reference a local variable:
mov eax, [esp+8]
and the instruction to reference a global variable:
mov eax, [0xb3a7135]
both take 1 (one!) clock cycle.
The only advantage, then, is that if every local variable is global, you wouldn't have to make room on the stack for local variables.
Adding a variable to the .data segment may actually increase the size of the executable, since the variable is actually contained in the file itself.
As caf mentions in the comments, stack-based variables only exist while the function is running - global variables take up memory during the entire execution of the program.
not quite sure what your confusion is?
int a = 10; means make a spot in memory, and put the value 10 at the memory address
if you want a to be 10
#define a 10
though more typically
#define TEN 10
Variables have storage space and can be modified. It makes no sense to stick them in the code segment, where they cannot be modified.
If you have code with int a=10 or even const int a=10, the compiler cannot convert code which references 'a' to use the constant 10 directly, because it has no way of knowing whether 'a' may be changed behind its back (even const variables can be changed). For example, one way 'a' can be changed without the compiler knowing is, if you have a pointer which points 'a'. Pointers are not fixed at runtime, so the compiler cannot determine at compile time whether there will be a pointer which will point to and modify 'a'.
This question already has answers here:
Closed 14 years ago.
Is it possible to write a C function that does the following?
Allocate a bunch of memory in the heap
Writes machine code in it
Executes those machines instructions
Of course, I would have to restore the state of the stack to what it was prior to the execution of those machine instructions manually, but I want to know if this is feasible in first place.
It's certainly possible. For various reasons, we've spent a lot of effort of the last 30-40 years trying to make it as difficult as possible, but it is possible. In most systems now, there are hardware and software mechanisms that attempt to protect data space from being executed.
The basics, though, are fairly straightforward: you construct a piece of code, and assemble it, either by hand or4 via a compiler. You then need a fragment of code space, so you insert the code into your program
unsigned int prgm[] = { 0x0F, 0xAB, 0x9A ... }; // Random numbers, just as an example
since you wanted to use the heap you need to malloc the space
void * myspace ;
if((myspace= malloc(sizeof(prgm))) != NULL) {
memcpy(myspace, pgrm, sizeof(pgrm));
} else { // allocation error
}
Now, what you need is a way to get the program counter to point to that chunk of data that is also your chunk of code. Here's where you need a little craftiness. Setting the program counter is no big deal; that's just a JUMP instruction for your underlying machine. But how to do that?
One of the easiest ways is by purposefully messing with the stack. The stack, again conceptually, looks something like this (the details depend on both your OS and compiler pairs, and on your hardware):
| subroutine return addr |
| parameters ... |
| automatic variables |
The basic trick here is to sneakily get the address of your code into the return address; when a routine returns, it basically jumps to that return addrfess. If you can fake it out, the PC will be set to where you like.
So, what you need is a routine, let's call it "goThere()"
void goThere(void * addr){
int a ; // observe above; this is the first space
// on the stack following the parameters
int * pa; // so we use it's address
pa = (&a - (sizeof(int)+(2*sizeof(void*))) ; // so use the address
// but back up by the size of an int, the pointer on the
// stack, and the return address
// Now 'pa' points to the routine's return add on the stack.
*pa = addr; // sneak the address of the new code into return addr
return ; // and return, tricking it into "returning"
// to the address of your special code block
}
Will it work? Well, maybe, depending on the hardware and OS. Most modern OS's will protect the heap (via memory mapping or similar) from the PC moving into it. This is a useful thing for security purposes, because we'd just as well not let you take that kind of complete control.
This is very similar to this question :)
Read calling code stored in the heap from vc++. On posix, mprotect seems to be appropriate (look into man mprotect):
char *mem = malloc(sizeof(code));
mprotect(mem, sizeof(code), PROT_READ|PROT_WRITE|PROT_EXEC);
memcpy(mem, code, sizeof(code));
// now arrange some code to jump to mem. But read the notes here on casting
// from void* to a function pointer:
// http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
However, it says:
Whether PROT_EXEC has any effect different from PROT_READ is architecture- and kernel version-dependent. On some hardware architectures (e.g., i386), PROT_WRITE implies PROT_READ.
So better, first check whether on your operation system, that works.
RE: manually restoring the stack
If you follow the calling conventions used by your platform / compiler inside the machine code you generate, then you shouldn't have to do any manual stack restoring. The compiler will do that for you, when you do
*pfunc(args)
it should add any appropriate pre or post call stack manipulation steps that are necessary.
Just make sure that you follow the right conventions inside the generated code, however.