How To Point To Address Of 32 Bit Register
This section describes the internal or machine representation of the basic types supported past Watcom C/C++:
An item of type char occupies 1 byte of storage. Its value is in the following range:
Note that char is, by default, unsigned. The Watcom C/C++ compiler option j tin can be used to change the default from unsigned to signed. If char is signed, an item of blazon char is in the post-obit range:
Yous can strength an particular of type char to be unsigned or signed regardless of the default past defining it to be of type unsigned char or signed char, respectively.
An particular of type brusque int occupies 2 bytes of storage. Its value is in the following range:
Note that short int is signed, and hence short int and signed brusk int are equivalent. If an item of type short int is to be unsigned, it must be defined equally unsigned brusk int. In this case, its value is in the following range:
An detail of type long int occupies 4 bytes of storage. Its value is in the following range:
Note that long int is signed, and hence long int and signed long int are equivalent. If an particular of type long int is to exist unsigned, it must be defined as unsigned long int. In this case, its value is in the following range:
An item of type int occupies iv bytes of storage. Its value is in the post-obit range:
Annotation that int is signed, and hence int and signed int are equivalent. If an particular of type int is to be unsigned, it must be defined equally unsigned int. In this case its value is in the following range:
If y'all are generating code that executes in 32-bit mode, long int and int are equivalent, unsigned long int and unsigned int are equivalent, and signed long int and signed int are equivalent. This may not be the case in other environments where int and brusk int are 2 bytes.
An item of type bladder is an gauge representation of a real number. Each detail of type float occupies 4 bytes. If yard is the magnitude of x (an detail of type float), and then x can be approximated if
Information of type float are represented internally as follows. Notation that bytes are stored in memory with the to the lowest degree significant byte commencement and the most pregnant byte terminal.
When the exponent field is all 0 bits, and the significand field is non-zero, so the quantity is a special value called a denormal or nonnormal number.
An item of type double is an approximate representation of a real number. The precision of an item of type double is greater than or equal to 1 of type float. Each item of type double occupies 8 bytes. If 1000 is the magnitude of 10 (an detail of type double), then ten can be approximated if
Information of type double are represented internally as follows. Note that bytes are stored in memory with the least meaning byte start and the most significant byte last.
When the exponent field is all 0 bits, and the significand field is non-naught then the quantity is a special value called a denormal or nonnormal number.
Calling conventions for not-80x87 applications
The following sections describe the calling conventions used when compiling with the fpc compiler option:
- Passing arguments using annals-based calling conventions
- Sizes of predefined types
- Size of enumerated types
- Effect of function prototypes on arguments
- Interfacing to assembly language functions
- Using stack-based calling conventions
- Functions with a variable number of arguments
- Returning values from functions
Passing arguments using register-based calling conventions
How arguments are passed to a part with register-based calling conventions is adamant by the size (in bytes) of the argument, and where in the argument listing the statement appears:
- Depending on the size, arguments are either passed in registers or on the stack. Arguments such as structures are almost ever passed on the stack since they're generally besides large to fit in registers.
- Since arguments are processed from left to correct, the first few arguments are likely to exist passed in registers (if they can fit) and, if the argument list contains many arguments, the last few arguments are likely to exist passed on the stack.
The registers used to laissez passer arguments to a function are EAX, EBX, ECX and EDX. The following algorithm describes how arguments are passed to functions.
Initially, the EAX, EDX, EBX and ECX registers are available for passing arguments. Note that registers are selected from this listing in the order in which they announced. That is, the first annals selected is EAX, and the concluding is ECX. For each statement Ai, starting with the leftmost argument, perform the following steps.
- If the size of Ai is 1 byte or ii bytes, catechumen it to iv bytes and proceed to the side by side stride. If Ai is of blazon unsigned char or unsigned curt int, it's converted to an unsigned int. If Ai is of type signed char or signed curt int, information technology'south converted to a signed int. If Ai is a 1-byte or 2-byte structure, the padding is determined past the compiler.
- If an argument has already been assigned a position on the stack, Ai volition also be assigned a position on the stack. Otherwise, proceed to the next step.
- If the size of Ai is 4 bytes, select a register from the list of available registers. If a annals is available, Ai is assigned that register. The register is and then removed from the list of available registers. If no registers are bachelor, Ai is assigned a position on the stack.
- If the type of Ai is far pointer, select a register pair from the post-obit listing of combinations: [EDX EAX] or [ECX EBX]. The first available register pair is assigned to Ai, and removed from the list of available pairs. The segment value will actually be passed in register DX or CX and the get-go in register EAX or EBX. If none of the above register pairs is bachelor, Ai is assigned a position on the stack. Note that 8 bytes are pushed on the stack even though the size of an item of blazon far pointer is vi bytes.
- If the blazon of Ai is double or bladder (in the absence of a function prototype), select a register pair from the post-obit listing of combinations: [EDX EAX] or [ECX EBX]. The commencement available register pair is assigned to Ai, and removed from the list of available pairs. The loftier-order 32 bits of the argument are assigned to the first register in the pair; the depression-order 32 bits are assigned to the second register in the pair. If none of the above annals pairs is bachelor, Ai is assigned a position on the stack.
- All other arguments are assigned a position on the stack.
Notation the following:
- Arguments that are assigned a position on the stack are padded to a multiple of four bytes. That is, if a 3-byte construction is assigned a position on the stack, 4 bytes are pushed on the stack.
- Arguments that are assigned a position on the stack are pushed onto the stack starting with the rightmost argument.
Sizes of predefined types
The following table lists the predefined types, their size as returned by the sizeof() function, the size of an argument of that type and the registers used to pass that argument if it'southward the but statement in the statement list.
Basic Type | sizeof() | Argument size | Registers used |
---|---|---|---|
char | 1 | iv | [EAX] |
short int | two | iv | [EAX] |
int | four | 4 | [EAX] |
long int | 4 | 4 | [EAX] |
float | 4 | 8 | [EDX EAX] |
double | 8 | 8 | [EDX EAX] |
about pointer | 4 | 4 | [EAX] |
far pointer | 6 | 8 | [EDX EAX] |
Provided no role prototypes exist, an argument is converted to a default type as described in the post-obit table.
Argument Type | Passed Equally |
---|---|
char | unsigned int |
signed char | signed int |
unsigned char | unsigned int |
brusk | unsigned int |
signed short | signed int |
unsigned short | unsigned int |
float | double |
Size of enumerated types
The integral type of an enumerated type is adamant by the values of the enumeration constants. In strict ANSI C mode, all enumerated constants are of type int. In the extensions mode, the compiler will use the smallest integral blazon possible (excluding long ints) that can correspond all values of the enumerated type. For instance, if the minimum and maximum values of the enumeration constants are in the range -128 through 127, the enumerated type is equivalent to a signed char (size = 1 byte). All references to enumerated constants in this instance will accept type signed char. An enumerated constant is e'er promoted to an int when passed as an argument.
Effect of function prototypes on arguments
Function prototypes define the types of the formal parameters of a part. Their appearance affects the fashion in which arguments are passed. An argument is converted to the type of the corresponding formal parameter in the part image. Consider the following example:
void image( float x, int i ); void chief() { float 10; int i; ten = three.fourteen; i = 314; epitome( x, i ); rtn( ten, i ); }
The role image for prototype() specifies that the beginning statement is to be passed as a float and the second argument is to be passed as an int. This means that the first statement is passed in annals EAX, and the 2nd argument in register EDX.
If no function prototype is given, every bit is the case for the part rtn(), the first argument is passed every bit a double, and the second argument would be passed as an int. This means that the outset argument is passed in registers EDX and EAX, and the second argument is passed in annals EBX.
Notation that even though both prototype() and rtn() were chosen with identical argument lists, the mode in which the arguments were passed was completely different, simply because a function image for prototype() was specified. Part prototyping is an first-class style to guarantee that arguments are passed as expected to your assembly language role.
Interfacing to associates language functions
Consider the following case:
void main() { double x; int i; double y; x = 7; i = 77; y = 777; myrtn( x, i, y ); }
myrtn() is an associates linguistic communication function that requires three arguments:
- the first argument is of blazon double
- the second argument is of type int
- the tertiary argument is once again of type double
Using the rules for register-based calling conventions, these arguments are passed to myrtn() in the post-obit mode:
- The first argument is passed in registers EDX and EAX, leaving EBX and ECX every bit available registers for other arguments.
- The second statement is passed in register EBX, leaving ECX as an bachelor annals for other arguments.
- The tertiary statement won't fit in register ECX (its size is 8 bytes), and hence is pushed on the stack.
Permit's look at the stack upon entry to myrtn():
Register EBP is normally used to accost arguments on the stack. Upon entry to the role, register EBP is set to signal to the stack, just before doing and so nosotros must relieve its contents. The following two instructions achieve this.
push EBP ; salve electric current value of EBP mov EBP,ESP ; become access to arguments
Later on executing these instructions, the stack looks like this:
As the above diagrams show, the third argument is at first eight from register EBP in a small code model, and offset 12 in a big code model.
Upon exit from myrtn(), nosotros must restore the value of EBP. The post-obit 2 instructions achieve this.
mov ESP,EBP ; restore stack pointer pop EBP ; restore EBP
The post-obit is a sample assembly language function that implements myrtn() for the pocket-size retentivity model (pocket-sized code, small information):
DGROUP group _DATA, _BSS _TEXT segment byte public 'CODE' assume CS:_TEXT assume DS:DGROUP public myrtn_ myrtn_ proc near push button EBP ; save EBP mov EBP,ESP ; go admission to arguments ; ; torso of office ; mov ESP,EBP ; restore ESP popular EBP ; restore EBP ret viii ; render and popular last arg myrtn_ endp _TEXT ends
The same function for a large memory model (big lawmaking, big data) is as follows:
DGROUP group _DATA, _BSS MYRTN_TEXT segment byte public 'CODE' assume CS:MYRTN_TEXT public myrtn_ myrtn_ proc far push EBP ; save EBP mov EBP,ESP ; become access to arguments ; ; trunk of function ; mov ESP,EBP ; restore ESP pop EBP ; restore EBP ret 8 ; return and pop final arg myrtn_ endp MYRTN_TEXT ends
Note the following:
- Global function names must be followed by an underscore. Global variable names must be preceded by an underscore.
- All used 80x86 registers must be saved on entry and restored on exit, except those used to pass arguments and return values. Notation that segment registers only have to saved and restored if you are compiling your application with the r choice.
- The direction flag must exist articulate earlier returning to the caller.
- In a small code model, any segment containing executable code must belong to the segment _TEXT and the class CODE. The segment _TEXT must accept a combine blazon of PUBLIC. On entry, CS contains the segment address of the segment _TEXT. In a big code model at that place is no restriction on the naming of segments that contain executable lawmaking.
- In a small data model, segment register DS contains the segment address of the group DGROUP. This isn't the case in a big data model.
- When writing assembly language functions for the small lawmaking model, you must declare them every bit nigh. If y'all wish to write assembly language functions for the big code model, you must declare them as far.
- In general, when naming segments for your code or information, you should follow the conventions described in ``Memory layout'' in the chapter 32-scrap Memory Models.
- If any of the arguments are pushed onto the stack, the called routine must pop them off the stack in the ret didactics.
Using stack-based calling conventions
Let's now consider the instance in the previous section, except this time nosotros'll use the stack-based calling convention. The virtually significant difference between the stack-based calling convention and the annals-based calling convention is the mode the arguments are passed. When using the stack-based calling conventions, no registers are used to pass arguments. Instead, all arguments are passed on the stack.
Let's look at the stack on entry to myrtn():
Register EBP is normally used to address arguments on the stack. Upon entry to the part, register EBP is fix to signal to the stack, but earlier doing so we must relieve its contents. The following two instructions achieve this.
push button EBP ; save electric current value of EBP mov EBP,ESP ; get access to arguments
After executing these instructions, the stack looks similar this:
As the above diagrams evidence, the arguments are all on the stack, and are referenced by specifying an offset from register EBP.
Upon exit from myrtn(), we must restore the value of EBP. The following two instructions achieve this:
mov ESP,EBP ; restore stack arrow popular EBP ; restore EBP
The post-obit is a sample associates language function that implements myrtn() for the minor retentiveness model (small code, pocket-sized information):
DGROUP group _DATA, _BSS _TEXT segment byte public 'CODE' assume CS:_TEXT assume DS:DGROUP public myrtn myrtn proc almost push EBP ; relieve EBP mov EBP,ESP ; get access to arguments ; ; body of function ; mov ESP,EBP ; restore ESP popular EBP ; restore EBP ret ; return myrtn endp _TEXT ends
The same office for the large retentiveness model (large code, big data) is as follows:
DGROUP group _DATA, _BSS MYRTN_TEXT segment byte public 'CODE' presume CS:MYRTN_TEXT public myrtn myrtn proc far push button EBP ; save EBP mov EBP,ESP ; get access to arguments ; ; body of part ; mov ESP,EBP ; restore ESP pop EBP ; restore EBP ret ; return myrtn endp MYRTN_TEXT ends
Annotation the following:
- Global part names must not exist followed by an underscore equally was the case with the register-based calling convention. Global variable names must non be preceded past an underscore as was the case with the register-based calling convention.
- All used 80x86 registers, except registers EAX, ECX and EDX must be saved on entry and restored on go out. Segment registers DS and ES must besides be saved on entry and restored on leave. Segment register ES doesn't have to exist saved and restored when using a memory model that isn't a small-scale data model. Note that segment registers merely have to be saved and restored if yous are compiling your application with the r option.
- The direction flag must be clear before returning to the caller.
- In a small-scale code model, whatever segment containing executable code must belong to the segment _TEXT and the grade CODE. The segment _TEXT must have a combine type of PUBLIC. On entry, CS contains the segment address of the segment _TEXT. In a big code model there's no restriction on the naming of segments that contain executable code.
- In a small information model, segment register DS contains the segment address of the group DGROUP. This isn't the case in a big information model.
- When writing assembly linguistic communication functions for the small code model, you must declare them as virtually. If you lot wish to write assembly language functions for the large code model, you must declare them as far.
- In general, when naming segments for your code or information, you lot should follow the conventions described in ``Retention layout'' in the chapter 32-bit Memory Models.
- The caller is responsible for removing arguments from the stack.
Functions with a variable number of arguments
A function prototype with a parameter list that ends with ``,...'' has a variable number of arguments. In this example, all arguments are passed on the stack. Since no prototyping information exists for arguments represented by ``,...'', those arguments are passed every bit described in the section ``Using Stack-Based Calling Conventions.''
Returning values from functions
The way in which role values are returned depends on the size of the return value. The following examples depict how part values are to be returned. They are coded for a pocket-size code model.
- 1-byte values are to be returned in annals AL.
_TEXT segment byte public 'Code' presume CS:_TEXT public Ret1_ Ret1_ proc well-nigh ; char Ret1() mov AL,'G' ret Ret1_ endp _TEXT ends end
- two-byte values are to be returned in register AX.
_TEXT segment byte public 'Code' assume CS:_TEXT public Ret2_ Ret2_ proc near ; short int Ret2() mov AX,77 ret Ret2_ endp _TEXT ends end
- iv-byte values are to exist returned in register EAX.
_TEXT segment byte public 'Code' assume CS:_TEXT public Ret4_ Ret4_ proc near ; int Ret4() mov EAX,7777777 ret Ret4_ endp _TEXT ends terminate
- 8-byte values, except structures, are to exist returned in registers EDX and EAX. When using the fpc (floating-betoken calls) pick, float and double are returned in registers. Run into ``Returning values in 80x87-based applications'' when using the fpi or fpi87 options.
.8087 _TEXT segment byte public 'CODE' assume CS:_TEXT public Ret8_ Ret8_ proc near ; double Ret8() mov EDX,dword ptr CS:Val8+4 mov EAX,dword ptr CS:Val8 ret Val8: dq seven.7 Ret8_ endp _TEXT ends finish
The .8087 pseudo-op must be specified so that all floating-point constants are generated in 8087 format.
- Otherwise, the caller allocates infinite on the stack for the return value and sets register ESI to indicate to this expanse. In a large data model, annals ESI contains an kickoff relative to the segment value in segment register SS.
_TEXT segment byte public 'CODE' assume CS:_TEXT public RetX_ ; ; struct int_values { ; int value1, value2, value3, value4, value5; ; }; ; RetX_ proc near ; struct int_values RetX() mov dwordptr SS:0[ESI],71 mov dwordptr SS:iv[ESI],72 mov dwordptr SS:viii[ESI],73 mov dwordptr SS:12[ESI],74 mov dwordptr SS:xvi[ESI],75 ret RetX_ endp _TEXT ends end
When returning values on the stack, remember to employ a segment override to the stack segment (SS).
The following is an case of a Watcom C/C++ plan that calls the above assembly linguistic communication subprograms.
#include <stdio.h> struct int_values { int value1; int value2; int value3; int value4; int value5; }; extern char Ret1(void); extern short int Ret2(void); extern long int Ret4(void); extern double Ret8(void); extern struct int_values RetX(void); void main() { struct int_values x; printf( "Ret1 = %c\n", Ret1() ); printf( "Ret2 = %d\due north", Ret2() ); printf( "Ret4 = %ld\n", Ret4() ); printf( "Ret8 = %f\n", Ret8() ); ten = RetX(); printf( "RetX1 = %d\n", x.value1 ); printf( "RetX2 = %d\due north", 10.value2 ); printf( "RetX3 = %d\north", 10.value3 ); printf( "RetX4 = %d\northward", x.value4 ); printf( "RetX5 = %d\n", ten.value5 ); }
The above function should exist compiled for a small code model (employ the mf , ms or mc compiler option).
Calling conventions for 80x87-based applications
When a source file is compiled by Watcom C/C++ with one of the fpi or fpi87 options, all floating-point arguments are passed on the 80x86 stack. The rules for passing arguments are as follows.
- If the argument isn't floating-indicate, use the procedure described earlier in this affiliate in the section ``Passing Arguments Using Register-based Calling Conventions.''
- If the argument is floating-point, it'southward assigned a position on the 80x86 stack.
Passing values in 80x87-based applications
Consider the following example:
extern void myrtn(int,bladder,double,long int); void master() { float x; double y; int i; long int j; ten = 7.7; i = seven; y = 77.77 j = 77; myrtn( i, 10, y, j ); }
myrtn() is an associates language function that requires four arguments:
- the first argument is of type int (four bytes)
- the second argument is of type float (4 bytes)
- the third statement is of type double (8 bytes)
- the fourth argument is of type long int (4 bytes)
When using the stack-based calling conventions, all of the arguments are passed on the stack. When using the register-based calling conventions, the to a higher place arguments are passed to myrtn() in the following way:
- The first statement is passed in register EAX, leaving EBX, ECX and EDX as available registers for other arguments.
- The 2d statement is passed on the 80x86 stack, since it's a floating-point argument.
- The third argument volition also be passed on the 80x86 stack, since it's a floating-point argument.
- The fourth argument is passed on the 80x86 stack, since a previous argument has been assigned a position on the 80x86 stack.
Retrieve, arguments are pushed on the stack from right to left. That is, the rightmost argument is pushed outset.
All arguments passed on the stack must be removed past the called part.
The following is a sample associates linguistic communication function that implements myrtn().
.8087 _TEXT segment byte public 'CODE' assume CS:_TEXT public myrtn_ myrtn_ proc most ; ; body of function ; ret sixteen ; render and pop arguments myrtn_ endp _TEXT ends end
Note the post-obit:
- Role names must exist followed by an underscore.
- All used 80x86 registers must be saved on entry and restored on exit except those used to laissez passer arguments and return values. Notation that segment registers just accept to saved and restored if you are compiling your application with the r option. In this instance, EAX doesn't have to be saved as information technology was used to pass the offset argument. Floating-point registers can be modified without saving their contents.
- The direction flag must be clear before returning to the caller.
- This part has been written for a small code model. Any segment containing executable code must belong to the course Lawmaking and the segment _TEXT. On entry, CS contains the segment accost of the segment _TEXT. The higher up restrictions don't employ in a large lawmaking memory model.
- When writing assembly language functions for a small code model, you must declare them every bit near. If you wish to write assembly language functions for a big code model, y'all must declare them as far.
Returning values in 80x87-based applications
When using the stack-based calling conventions with fpi or fpi87 , floating-point values are returned in registers. Unmarried precision values are returned in EAX, and double precision values are returned in EDX:EAX.
When using the annals-based calling conventions with fpi or fpi87 , floating-bespeak values are returned in ST(0). All other values are returned in the manner described before in this chapter in the section ``Returning Values from Functions.''
How To Point To Address Of 32 Bit Register,
Source: https://users.pja.edu.pl/~jms/qnx/help/watcom/compiler-tools/ccall32.html
Posted by: bertrandbelity.blogspot.com
0 Response to "How To Point To Address Of 32 Bit Register"
Post a Comment