banner



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.

Southward
S = Sign fleck (0=positive, 1=negative)
Exponent
The exponent bias is 127 (that is, exponent value 1 represents two**-126, exponent value 127 represents 2**0, exponent value 254 represents 2**127, then on). The exponent field is 8 bits long.
Significand
The leading scrap of the significand is always 1, hence it isn't stored in the significand field. Thus the significand is e'er normalized. The significand field is 23 bits long.
Zip
A real zero quantity occurs when the sign bit, exponent, and significand are all zippo.
Infinity
When the exponent field is all 1 bits, and the significand field is all zero bits, and so the quantity represents positive or negative infinity, depending on the sign bit.
Not Numbers
When the exponent field is all 1 $.25, and the significand field is non-zero, then the quantity is a special value called a NAN (Not-A-Number).

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.

South
S = Sign scrap (0=positive, 1=negative)
Exponent
The exponent bias is 1023 (that is, exponent value one represents two**-1022, exponent value 1023 represents ii**0, exponent value 2046 represents 2**1023, and and so on). The exponent field is eleven bits long.
Significand
The leading scrap of the significand is e'er 1, hence it isn't stored in the significand field. Thus the significand is always normalized. The significand field is 52 bits long.
Zip
A double-precision zippo quantity occurs when the sign bit, exponent, and significand are all zero.
Infinity
When the exponent field is all 1 bits, and the significand field is all zippo bits, and so the quantity represents positive or negative infinity, depending on the sign fleck.
Not Numbers
When the exponent field is all 1 bits, and the significand field is not-cypher, then the quantity is a special value called a NAN (Not-A-Number).

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. All other arguments are assigned a position on the stack.

Notation the following:

  1. 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.
  2. 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]
The size of the argument listed in the table assumes that no function prototypes are specified. Role prototypes bear upon the way arguments are passed. This is discussed in the section ``Issue of Role Prototypes on Arguments.''

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
Past default, char is unsigned.

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:

  1. The first argument is passed in registers EDX and EAX, leaving EBX and ECX every bit available registers for other arguments.
  2. The second statement is passed in register EBX, leaving ECX as an bachelor annals for other arguments.
  3. 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():

fig: ./images/stk32_1.gif The render address is the top element on the stack. In a small code model, the render address is one double give-and-take (32 bits).

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:

fig: ./images/stk32_2.gif

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:

  1. Global function names must be followed by an underscore. Global variable names must be preceded by an underscore.
  2. 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.
  3. The direction flag must exist articulate earlier returning to the caller.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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():

fig: ./images/stk32_3.gif The render address is the elevation chemical element on the stack. In a small code model, the return address is ane double word (32 bits).

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:

fig: ./images/stk32_4.gif

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:

  1. 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.
  2. 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.
  3. The direction flag must be clear before returning to the caller.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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. 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            
  2. 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            
  3. 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            
  4. 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.

  5. 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).

Returning values from functions in the stack-based calling convention is the same as returning values from functions in the register-based calling convention when using the fpc 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.

  1. 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.''
  2. If the argument is floating-point, it'southward assigned a position on the 80x86 stack.
When compiling using the fpi or fpi87 options, the method used for passing floating-point arguments in the stack-based calling convention is identical to the method used in the annals-based calling convention. Withal, when compiling using the fpi or fpi87 options, the method used for returning floating-point values in the stack-based calling convention is unlike from the method used in the annals-based calling convention. The register-based calling convention returns floating-point values in ST(0), whereas the stack-based calling convention returns floating-point values in EDX and EAX.

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:

  1. The first statement is passed in register EAX, leaving EBX, ECX and EDX as available registers for other arguments.
  2. The 2d statement is passed on the 80x86 stack, since it's a floating-point argument.
  3. The third argument volition also be passed on the 80x86 stack, since it's a floating-point argument.
  4. 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.

Any assembly language function must obey the following rule:

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:

  1. Role names must exist followed by an underscore.
  2. 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.
  3. The direction flag must be clear before returning to the caller.
  4. 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.
  5. 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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel