Page 1 of 1

Microsoft : The #pragma Preprocessing Directive - Part II Rate Topic: -----

#1 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Posted 14 April 2011 - 08:51 AM

Microsoft : The #pragma Preprocessing Directive - Part II

Introduction

This pair of tutorials concentrates on one of the preprocessor directives, namely the #pragma directive. This directive provides the developer with very fine control of the code produced by the C/C++ compiler and it is this fine control we shall be concentrating on here.

The first tutorial looked at the power of the pack directive (found here). This second tutorial concerns itself with how the developer has fine control over where data and functions reside in the executable.

Segments

The compiler allocates program declarations to different sections or segments of the object file (and ultimately by the linker into the executable) depending on their usage. For example a constant declaration will be placed into a segment within the executable that when loaded by the operating system will appear in a page that has read-only access. Data declarations will be placed into a segment that when loaded will appear in a page that has read and write access. Functions declarations will appear in a page that has read and execute access.

There are several pragma directives that permit the developer to alter this (although a word of warning might not go amiss here, as it can be potentially very dangerous to start putting constant declarations into memory that will be loaded with read and write access as this could give rise to security issues).

The simple format for this directive is #pragma segment_name("name") where segment_name can be one of bss_seg for uninitialized data, data_seg for initialized data, const_seg for constants and code_seg for function declarations.

Now ordinarily, the developer is not bothered with where exactly data is placed, so long as it is in the correct segment with the correct access rights. Having said that, there are situations where it might be advantageous to specify new segments of a specific type. For example if we were to code the following:

#pragma data_seg("martyn")
int this_array[25];



then providing the segment "martyn" had not been used before, we can guarantee that this_array starts on a page boundary (i.e. the last 12 bits are zero as a page is 4096 bytes in length).

Furthermore, if we changed this slightly and coded:

#pragma data_seg(push)
#pragma data_seg("martyn")
int this_array[25];
#pragma data_seg(pop)
char * foo[25];
#pragma data_seg(push)
#pragma data_seg("martyn")
int that_array[25];
#pragma data_seg(pop)



then providing the packing was set to one byte, that_array will follow on from this_array seamlessly, even though we have defined foo between the two arrays. This is because foo would be placed in the current segment and not in the segment named "martyn".

Conclusion

I have used this feature in past projects to great effect, but in their infinite wisdom, Microsoft seem to have removed the feature that was present in earlier (years ago) compilers. What you are left with is a set of directives that do not seem to be useful any more! Perhaps you can think of some useful way to use them.

It should be noted that there is also the __pragma keyword which allows you to define segments within a macro.

This post has been edited by Martyn.Rae: 14 April 2011 - 12:04 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Microsoft : The #pragma Preprocessing Directive - Part II

#2 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2247
  • View blog
  • Posts: 9,237
  • Joined: 18-February 07

Posted 19 May 2011 - 01:14 PM

WOW! Learn something new every day! However this does not seem to be working. The data still gets placed in the .bss segment. Maybe that is as-per-design though?

#pragma code_seg(push)
#pragma code_seg(".dynamic")
char buffer[1024*32];
#pragma code_seg(pop)

#pragma data_seg(push)
#pragma data_seg(".testing")
char tbuffer[1024*32];
#pragma data_seg(pop)

typedef int (*EntryFunction)(int, char**);


int main() {
    EntryFunction progMain = (EntryFunction)&buffer;
    return 0;
}


; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

	TITLE	C:\CProjects\Forum Help\testSegements.cpp
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC	?buffer@@3PADA					; buffer
PUBLIC	?tbuffer@@3PADA					; tbuffer
_BSS	SEGMENT
?buffer@@3PADA DB 08000H DUP (?)			; buffer
?tbuffer@@3PADA DB 08020H DUP (?)			; tbuffer
_BSS	ENDS
PUBLIC	_main
; Function compile flags: /Odtp
_TEXT	SEGMENT
_progMain$ = -4						; size = 4
_main	PROC
; File c:\cprojects\forum help\testsegements.cpp
; Line 14
	push	ebp
	mov	ebp, esp
	push	ecx
; Line 15
	mov	DWORD PTR _progMain$[ebp], OFFSET ?buffer@@3PADA ; buffer
; Line 16
	xor	eax, eax
; Line 17
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1